【Java】Collection子接口:其二 Set 组接口

Collection子接口:其二 Set 组接口 

- Set接口是Collection的子接口,Set没有提供额外的方法

- Set集合中不允许包含重复的元素,如果重复添加,只保留最新添加的那一个

- Set判断两个元素是否相同不是 == 判断,而是取equals()方法

Set主要实现类:

HashSet、LinkedHashSet、TreeSet

- HashSet  Set主要接口实现类、线程不安全的、可存储Null值

- LinkedHashSet  继承了HashSet、遍历内部数据,可按照添加时的顺序遍历

- TreeSet  底层存储结构是红黑树【二叉树】,按照指定属性进行排序

Set底层的说明,红康老师讲的还是不解,决定留在数据结构篇再来细谈

https://www.bilibili.com/video/BV1Kb411W75N?p=537

扫描二维码关注公众号,回复: 11005047 查看本文章

底层算法的哈希码

https://www.cnblogs.com/mindzone/p/12736516.html

 1 public class CollectionTest {
 2     public static void main(String[] args) {
 3         Set set = new HashSet();
 4 
 5         set.add("阿伟");
 6         set.add("杰哥");
 7         set.add("1376");
 8         set.add("先辈");
 9         set.add("Van");
10         set.add("佟大为");
11         set.add("1376");
12         set.add(new Student("小明",12));
13         set.add(new Student("小明",12));
14 
15         Iterator iterator = set.iterator();
16 
17         while(iterator.hasNext()){
18             Object next = iterator.next();
19             System.out.println(next);
20         }
21         //  阿伟  Van  1376   佟大为   杰哥  先辈
22         //  无序性不是遍历的结果没有顺序(不是随机性) 存储的数据不是按照索引顺序排列的,根据数据的Hash值添加
23         //  不可重复性 这里添加了同一字符串1376,从哈希码可以判断是一样,set集合只会保留其中一个
24 
25         //  如果是对象就不一样了,这里依然会保留两个同属性对象,底层哈希码是不一样的
26         //  再重写equals & hashCode 之后只保留一个对象了, 调用add方法时,set会调用对象的equals方法判断,为true将不会添加
27     }
28 }
29 
30 
31 class Student{
32     private String name;
33     private Integer age;
34 
35     public String getName() {
36         return name;
37     }
38 
39     public void setName(String name) {
40         this.name = name;
41     }
42 
43     public Student(String name, Integer age) {
44         this.name = name;
45         this.age = age;
46     }
47 
48     public Integer getAge() {
49         return age;
50     }
51 
52     public void setAge(Integer age) {
53         this.age = age;
54     }
55 
56     @Override
57     public String toString() {
58         return "Student{" +
59                 "name='" + name + '\'' +
60                 ", age=" + age +
61                 '}';
62     }
63 
64     @Override
65     public boolean equals(Object o) {
66         if (this == o) return true;
67         if (!(o instanceof Student)) return false;
68         Student student = (Student) o;
69         return Objects.equals(getName(), student.getName()) &&
70                 Objects.equals(getAge(), student.getAge());
71     }
72 
73     @Override
74     public int hashCode() {
75         return Objects.hash(getName(), getAge());
76     }
77 }

LinkedHashSet,是HashSet的子类

添加数据的同时每个数据维护了两个引用,记录前一个数据和后一个数据

对于频繁的遍历操作,LinkedHashSet效率高于HashSet

public class CollectionTest {
    public static void main(String[] args) {
        Set set = new LinkedHashSet();

        set.add("阿伟");
        set.add("杰哥");
        set.add("1376");
        set.add("先辈");
        set.add("Van");
        set.add("佟大为");
        set.add("1376");

        Iterator iterator = set.iterator();

        while(iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
    }
}

TreeSet存储的数据只能是同一个类型的数据

自定义数据类型或者其他的基本类型封装类

TreeSet方式的判断是以Comparable接口实现的compareTo方法操作的【自然排序方式】

0 表示相同 TreeSet将会认为是重复,不再添加重复的元素

 1 public class CollectionTest {
 2     public static void main(String[] args) {
 3         Set set = new TreeSet();
 4 
 5         set.add(new Person("Jimmy",17));
 6         set.add(new Person("Mike",13));
 7         set.add(new Person("Jim",15));
 8         set.add(new Person("Jack",12));
 9         set.add(new Person("Jerry",18));
10         set.add(new Person("Jack",56));
11 
12         Iterator iterator = set.iterator();
13 
14         while(iterator.hasNext()){
15             Object next = iterator.next();
16             System.out.println(next);
17         }
18     }
19 }
20 
21 
22 // 需要实现Comparable接口
23 class Person implements Comparable{
24     private String name;
25     private Integer age;
26 
27     public Person(String name, Integer age) {
28         this.name = name;
29         this.age = age;
30     }
31 
32     public String getName() {
33         return name;
34     }
35 
36     public void setName(String name) {
37         this.name = name;
38     }
39 
40     public Integer getAge() {
41         return age;
42     }
43 
44     public void setAge(Integer age) {
45         this.age = age;
46     }
47 
48     @Override
49     public String toString() {
50         return "Person{" +
51                 "name='" + name + '\'' +
52                 ", age=" + age +
53                 '}';
54     }
55 
56     // 重写此方法
57     @Override
58     public int compareTo(Object o) {
59         if (o instanceof Person){
60             Person p = (Person)o;
61             int compare = this.name.compareTo(p.name); // 掉用String的compareTo方法,不是本地的
62             if (compare != 0) return compare;
63             else return Integer.compare(this.age,p.age);    // 如果相同,再compare第二属性
64         }else throw new RuntimeException("装入的类型不匹配!");
65     }
66 }

详细红黑树可以参考自视频里面的这篇链接,作者博客已经搬迁了啊

https://www.yycoding.xyz/post/2014/3/27/introduce-red-black-tree

除了上面的自然排序,也支持定制排序

 1 public class CollectionTest {
 2     public static void main(String[] args) {
 3         Comparator comparator = new Comparator() {
 4             // 按照年龄从小到大排列,一样剔除
 5             @Override
 6             public int compare(Object o1, Object o2) {
 7                 if (o1 instanceof Person && o2 instanceof Person){
 8                     Person p1 = (Person)o1;
 9                     Person p2 = (Person)o2;
10                     return Integer.compare(p1.getAge(),p2.getAge());
11                 }else throw new RuntimeException("类型不匹配!");
12             }
13         };
14 
15         // 如果定义了定制排序,创建Set集合初始化时,注入定制比较器,TreeSet就会默认使用此比较
16         Set set = new TreeSet(comparator);
17 
18         set.add(new Person("Jimmy",17));
19         set.add(new Person("Mike",13));
20         set.add(new Person("Jim",15));
21         set.add(new Person("Jack",12));
22         set.add(new Person("Jerry",18));
23         set.add(new Person("Jack",56));
24 
25         Iterator iterator = set.iterator();
26 
27         while(iterator.hasNext()){
28             Object next = iterator.next();
29             System.out.println(next);
30         }
31     }
32 }
33 
34 
35 // 需要实现Comparable接口
36 class Person implements Comparable{
37     private String name;
38     private Integer age;
39 
40     public Person(String name, Integer age) {
41         this.name = name;
42         this.age = age;
43     }
44 
45     public String getName() {
46         return name;
47     }
48 
49     public void setName(String name) {
50         this.name = name;
51     }
52 
53     public Integer getAge() {
54         return age;
55     }
56 
57     public void setAge(Integer age) {
58         this.age = age;
59     }
60 
61     @Override
62     public String toString() {
63         return "Person{" +
64                 "name='" + name + '\'' +
65                 ", age=" + age +
66                 '}';
67     }
68 
69     // 重写此方法
70     @Override
71     public int compareTo(Object o) {
72         if (o instanceof Person){
73             Person p = (Person)o;
74             int compare = this.name.compareTo(p.name); // 掉用String的compareTo方法,不是本地的
75             if (compare != 0) return compare;
76             else return Integer.compare(this.age,p.age);    // 如果相同,再compare第二属性
77         }else throw new RuntimeException("装入的类型不匹配!");
78     }
79 }

没有写定制排序才会按照equals方法排序

猜你喜欢

转载自www.cnblogs.com/mindzone/p/12742866.html