Set接口

来自java.util是和List一样属于Collection的子接口,

方法都是来自Collection

Set集合中的对象不会记录顺序只是简单的把元素添加进集合

因此它不能添加重复元素,它的比较流程如下

集合-续_存储位置

因此在添加自定义对象想达到想要的去重效果就要重写HashCode()与equals()方法

原HashCode()方法定义在Object,每次创建对象都会带有一个hash值,对应内存地址的一个编号。因此不同的对象的都不一样,我们在添加一个自定义对象去重时就需要在添加同一个类型对象时,去比较属性是不是一样来决定是否加进去。也就需要将hashCode()重写为是一个类型就是返回相同的值,再用equals来比较内容,不是一个类型就不用比较内容了直接添加。

class Animal{  String name;  Animal(String name){    this.name = name;  }  @Override  public String toString() {// 重写toString打印内容    return "Animal [name=" + name + "]";  }  @Override  public int hashCode() {// 判断是否是一类型    final int prime = 31;    int result = 1;    result = prime * result + ((name == null) ? 0 : name.hashCode());    return result;  }  @Override  public boolean equals(Object obj) {// 重写equals()比较内容是否相等    if (this == obj)      return true;    if (obj == null)      return false;    if (getClass() != obj.getClass())      return false;    Animal other = (Animal) obj;    if (name == null) {      if (other.name != null)        return false;    } else if (!name.equals(other.name))      return false;    return true;  }  }class test{  String name;// 定义个和Animal相同的字段  test(String name){    this.name = name;  }  public static void main(String[] args) {    Set s = new HashSet();    s.add(new Animal("狗"));    s.add(new Animal("猫"));    s.add(new Animal("狗"));    s.add(new test("狗"));    System.out.println(s);      }}// 结果就验证了上图的流程,添加上了三个元素。结果:   [Animal [name=狗], first.a.test@15db9742, Animal [name=猫]]

 

HashSet类

Set接口的实现类,也没有什么特有方法

它的子类LinkedHashSet是链表结构所以是逻辑有序的每个元素的后继是对应添加时的顺序

下面做两个小练习

小练习1:生成10个100以内不重复的随机数

小练习2:去重(对键盘输入的字符)

 

import java.util.HashSet;import java.util.Random;


class test{    public static void main(String[] args) {    Random r = new Random();    HashSet<Integer> h = new HashSet<Integer>();        for(int i=0; i<10;i++) {      h.add(r.nextInt(100));    }    System.out.println(h);      }}
[80, 33, 99, 83, 38, 86, 10, 27, 12, 30]
import java.util.HashSet;import java.util.Scanner;


class test{    public static void main(String[] args) {    Scanner sc = new Scanner(System.in);    String sr = sc.nextLine();    HashSet<Character> h = new HashSet<Character>();    for(int i = 0; i<sr.length(); i++) {      h.add(sr.charAt(i));// 遍历添加字符串    }    System.out.println(h);  }}

输入:  sdadaq3dada结果:  [a, q, s, 3, d]

 

TreeSet类

Set接口的实现类

import java.util.TreeSet;
class test{    public static void main(String[] args) {        TreeSet t =new TreeSet();    t.add("f");    t.add("a");    t.add("3");    t.add("1");    t.add("b");    System.out.println(t);        TreeSet t1 = new TreeSet();    t1.add(2);    t1.add(8);    t1.add(4);    t1.add(1);    System.out.println(t1);      }}/* 上面代码中添加的一个是Character,一个是Integer,它们这两个类也是实现接口并且重写了CompareTo()才可以被添加*/
结果:    [1, 3, a, b, f]    [1, 2, 4, 8]
  • 它会对添加到里面的元素进行排序通过类的比较方法

  • 所以就算没有指明泛型也只能添加一种类型。

    这样才能比较,不然运行报错

  • 添加的元素都是保证同一种类型,比较时会调用重写的CompareTo()方法

  • 所以要添加进TreeSet的类型,此类就必须得实现Comparable并且重写CompareTo()方法

  • 或者单独定义一个类实现Comparator做比较器,在创建TreeSet集合时将比较器对象传入构造器中。

  • 排序是以二叉树的形式,compareTo会有int类型的返回值如果是正数表示大放右边,负就表示小放左边,如果是0则相同不能添加成功。最后以中序遍历得到顺序

下面看一下Integer中重写的compareTo()方法

集合-续_比较器_02

集合-续_比较器_03

知道怎么排之后现在就来做一个自定义的类完成添加到TreeSet当中

定义一个人类按照年龄排序

import java.util.TreeSet;
class Person implements Comparable<Person>{
  String name ;  int age;  public Person(String name,int age) {    this.age = age;    this.name = name;      }    @Override  public String toString() {    return "Person [name=" + name + ", age=" + age + "]";  }
  @Override  public int compareTo(Person another) {    // TODO Auto-generated method stub    if(this.age>another.age) {// 大于则返回正,放右      return 1;    }else if(this.age<another.age) {// 小则返回负,放左      return -1;    }else {// 相同时并不想只是因为年龄相同就返回0添加不上      if(this.name.equals(another.name)) {//就再进行判断如果名字也相同才是我们不想让他添加上的        return 0;      }else{// 仅仅只是年龄相同的        return 1;      }    }      }  }
class test{    public static void main(String[] args) {        TreeSet<Person> t = new TreeSet<Person>();    t.add(new Person("张三", 15));    t.add(new Person("李四", 17));    t.add(new Person("王五", 24));    t.add(new Person("马六", 13));    t.add(new Person("张三", 15));        System.out.println(t);      } }

结果:[Person [name=马六, age=13], Person [name=张三, age=15], Person [name=李四, age=17], Person [name=王五, age=24]]

Map集合

Map集合没有继承Collection接口,它提供的时key到value的映射。一个Map中不能包含相同的key,一个key只能有一个value与之对应。key还决定了存储对象在映射中的存储位置,但并不是由key对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值来确定存储对象在映射中的存储位置

常用方法试例:

import java.util.HashMap;import java.util.Map;
class test{    public static void main(String[] args) {        Map<String, Integer> m = new HashMap<>();    m.put("第一个", 1);// 添加元素    m.put("第二个", 2);    m.put("第三个", 3);    m.put("第四个", 4);    m.put("第一个",6);// 修改    System.out.println(m);    System.out.println(m.containsKey("第一个"));// 是否有key叫“第一个”    System.out.println(m.containsValue(3));// 是否有为3的value    System.out.println(m.get("第一个"));// 得到指定key的value    System.out.println(m.keySet());// 得到key的集合    System.out.println(m.values());// 得到value的集合    System.out.println(m.size());// 元素的数量    m.remove("第三个");// 移除指定key的元素    System.out.println(m);          } }

结果:    {第二个=2, 第四个=4, 第三个=3, 第一个=6}    true    true    6    [第二个, 第四个, 第三个, 第一个]    [2, 4, 3, 6]    4    {第二个=2, 第四个=4, 第一个=6}

它的实现类HashMap,TreeMap等的使用和HashSet,TreeSet一样,怎样去重怎样排序怎样遍历等等