2020.11.21 Set介面

段茜琳發表於2020-11-21

Set介面

共同特點:不允許有重複元素
1.HashSet
無序(不是按照新增順序排的),底層是HashMap。
如果類中沒有重寫hashCode(),那麼會呼叫Object中的hashCode()(不會重複)算出物件的hash值。
(1)新增時根據內容的hash值,再經過hash函式計算得到元素的hash表中儲存的位置。
(2)向HashSet中新增元素時是如何判定重複元的?
底層是雙保險的,既要提高判斷效率,還要安全可靠,首先會獲得新增內容hash值,判斷hash值在集合中是否存在,但是內容不同時,hash值可能會相同,那麼就不可靠,在hash值相同時,會呼叫equals()比較內容是否相等。
(3)重寫Object類中的hashCode(),來自己根據物件中包含的內容計算hash值,效率高,但是會重複,當hash值重複時,會呼叫equals()進行內容判斷,效率低,但是安全。

public class Student implements Comparable<Student>{
    private int num;
    private String name;

    @Override
    public int compareTo(Student o) {
        return this.num-o.num;//用哪個屬性比較,哪個屬性就不能重複
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student(int num, String name) {
        this.num = num;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "num=" + num +
                ", name='" + name + '\'' +
                '}';
    }

    //當hash值出現重複時,會呼叫equals()進行內容判斷,效率低,安全
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return num == student.num &&
                Objects.equals(name, student.name);
    }

    //重寫Object類中的hashCode(),來自己根據物件中包含的內容計算hash值   效率高,會出現重複
    @Override
    public int hashCode() {
        return Objects.hash(num, name);//比較物件中內容的hash值
    }
}
public class HashSetDemo {
    public static void main(String[] args) {
        /*
        * HashSet元素是無序的,(不是按照新增順序排列的),
        * HashSet底層是HashMap
        * */
        /*Set<String> set = new HashSet<>();
        set.add("s");
        set.add("s");
        set.add("a");
        set.add("張三");
        set.add("a");
        set.add("d");
        set.add("d");
        set.add("張三");
        System.out.println(set);*/
        /*
        * 如果類中沒有重寫hashCode();那麼會呼叫Object類中的hashCode()(不會重複),算出物件的hash值*/
        /*Student s = new Student();
        System.out.println(s);*/
        /*
        * 新增時根據內容的hash值,在經過hash函式計算得到的元素在hash表中儲存的位置
        * */
        /*
        * 向HashSet中新增元素時是如何判定重複元素的?
        *   底層是雙保險的,既要提高判斷效率,還要安全可靠
        * 首先會獲得新增內容的hash值,判斷hash值在集合中是否存在
        * 但是內容不同時,hash值可能會相同,那麼就不可靠
        * 在hash值相同時,會呼叫equals()比較內容是否相同*/

        HashSet<Student> set = new HashSet<>();
        set.add(new Student(101,"Bob"));
        set.add(new Student(101,"Bob"));
        set.add(new Student(102,"Jim"));
        set.add(new Student(103,"Tom"));
        //此時HashSet中新增的是物件,hash值一定不同,所以會出現重複
        System.out.println(set);
        /*[Student{num=102, name='Jim'}, Student{num=101, name='Bob'},
         Student{num=101, name='Bob'}, Student{num=103, name='Tom'}]*/

        //在Student類中重寫hashCode()和equals()後,判斷物件中內容的hash值,就會得出重複的
        /*
        * [Student{num=101, name='Bob'}, Student{num=102, name='Jim'}, Student{num=103, name='Tom'}]*/
    }
}

2.TreeSet
不可以儲存重複元素,有序(按照內容的自然順序排列),資料型別必須實現Comparable介面,重寫CompareTo(),底層使用的是紅黑樹。

public class TreeSetDemo {
    public static void main(String[] args){
        /*
        * TreeSet:
        * 不可以儲存重複元素
        * 有序(按照內容的自然順序排序)
        * 資料型別必須實現Comparable介面  重寫compareTo()
        * 底層使用的是紅黑樹*/
        TreeSet<String> tset = new TreeSet<>();
        tset.add("b");
        tset.add("c");
        tset.add("b");
        tset.add("a");
        tset.add("b");
        tset.add("a");
        System.out.println(tset);//[a, b, c]
        TreeSet<Integer> tset1 = new TreeSet<>();
        tset1.add(1);
        tset1.add(1);
        tset1.add(0);
        tset1.add(3);
        tset1.add(4);
        tset1.add(3);
        System.out.println(tset1);//[0, 1, 3, 4]
        //向TreeSet中新增元素時呼叫compareTo()比較大小,小於0  等於0(重複) 大於0
        TreeSet<Student> set = new TreeSet<>();
        Student s1 = new Student(101,"Bob");
        Student s2 = new Student(103,"Make");
        Student s3 = new Student(105,"Tom");
        Student s4 = new Student(101,"Tom");
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        System.out.println(set);
        /*
        * [Student{num=101, name='Bob'}, Student{num=103, name='Make'}, Student{num=105, name='Tom'}]*/
        /*
        * 如果類中沒有實現Comparable介面 重寫compareTo() 會丟擲異常
        *ClassCastException */

        //Set介面集合迭代
        for(Student s:set){
            System.out.println(s);
        }
        /*
        * Student{num=101, name='Bob'}
          Student{num=103, name='Make'}
          Student{num=105, name='Tom'}*/

        Iterator it = set.iterator();
        while (it.hasNext()){
            Object stu = it.next();
            System.out.println(stu);
        }
        /*
        * Student{num=101, name='Bob'}
          Student{num=103, name='Make'}
          Student{num=105, name='Tom'}*/
    }
}

3.Set介面迭代
(1)增強for迴圈
(2)迭代器(Iterator)