1. 程式人生 > 實用技巧 >集合:set介面及其實現類(HashSet、TreeSet底層結構)

集合:set介面及其實現類(HashSet、TreeSet底層結構)

1、set介面

(1)特點

  • 元素不能重複(equals判斷)
  • 無序
    @Test
    public void test1() {
        Set set=new HashSet();
        set.add("zhai");
        set.add("123");
        set.add("null");
        set.add("123");
        set.add("90");
        System.out.println(set);
    }
D:\IdeaProjects\test_03\src\com\zhb\test\DateDemo.java

注意:Treeset不允許新增null元素

(2)特有方法

沒有特有方法,主要是重collection介面繼承來的

(3)遍歷方式

和collection介面的遍歷方式相同:迭代器、增強for

2、HashSet底層結構

(1)底層結構

  • 雜湊表
public HashSet() {
        map = new HashMap<>();
    }

因為HashSet維護的是一個HashMap物件,而HashMap維護的是一個雜湊表,兩者都是基於hash結構的

  • 無序:根據雜湊值確定元素在雜湊表中的位置

(2)去除重複原理

原理:

先獲取元素的雜湊值,通過一些運算獲取一個整數索引index(要存放在陣列的位置)

如果索引處沒有元素,則直接新增

如果索引處有其他元素,則需要進行equals判斷,如果不相等,則以連結串列的形式追加到已有元素的後面並返回true,如果相等則直接覆蓋並返回false

如果不是雜湊表的結構,需要進行大量的equals判斷,雜湊表的使用大大減少了equals的使用

重寫equals與hashCode方法(https://www.cnblogs.com/zhai1997/p/11354885.html

儲存已經存在的資料型別的資料,不用重寫equals和hashcode方法,即可去除重複元素

儲存自定義型別的資料需要重寫equals和hashcode方法

3、TreeSet底層結構

(1)底層結構

基於map物件(TreeMap),treeMap的底層是紅黑樹的結構,可以實現對元素的排序

(2)特點

  • 不允許重複
  • 可以實現對裡面的元素進行排序(自然排序、定製排序)

  • 紅黑樹儲存的時候是左邊的存較小的元素,右邊儲存較大的元素,取出的時候可以按順序取出,先取出20,然後25... ...
  • 紅黑樹與二叉樹的不同是,紅黑樹給二叉樹標記了顏色,例如:左邊紅色右邊黑色,當左邊的紅色元素過多右邊黑色元素過少的時候,紅黑樹就失去了平衡,此時就要重新打亂順序重新選出根元素,使得兩邊保持平衡
  • 紅黑樹是二叉樹的一種

(3)TreeSet的使用

 @Test
    public void test1() {
        Set set=new TreeSet();
        set.add(new Student("zhai",12));
        set.add(new Student("zz",13));
        set.add(new Student("zhang",14));
        set.add(new Student("liu",19));
        set.add(new Student("zhang",14));
        for (Object s: set){
            System.out.println(s);
        }
    }
java.lang.ClassCastException: com.zhb.domain.Student cannot be cast to java.lang.Comparable

報錯的型別是型別轉換異常,原因是新增元素的時候在確定元素在二叉樹中的位置的時候,需要當前元素與結點元素進行比較,小的左,大的右,相等的話不新增,但是物件不具有比較性,因此報錯

要讓其具有比較性有兩種方法:

自然排序:

public class Student implements Comparable{
    public String sname;
    public int age;

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

    public Student(String sname, int age) {
        this.sname = sname;
        this.age = age;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    @Override
    public int compareTo(Object o) {
        Student s=(Student)o;
        return Integer.compare(this.age,s.age);
    }
}
Student{sname='zhai', age=12}
Student{sname='zz', age=13}
Student{sname='zhang', age=14}
Student{sname='liu', age=19}

此方法需要實現介面重寫方法

定製排序:

 @Test
    public void test1() {
        Set set=new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Student s1=(Student)o1;
                Student s2=(Student)o2;
                return Integer.compare(s1.getAge(),s2.getAge());
            }
        });
        set.add(new Student("zhai",12));
        set.add(new Student("zz",13));
        set.add(new Student("zhang",14));
        set.add(new Student("liu",19));
        set.add(new Student("zhang",14));
        for (Object s: set){
            System.out.println(s);
        }
    }
Student{sname='zhai', age=12}
Student{sname='zz', age=13}
Student{sname='zhang', age=14}
Student{sname='liu', age=19}

在定義TreeSet的同時定義比較器

(4)新增方法原理

底層是treemap的新增:

進行元素的比較:

呼叫的比較器:

(5)如何實現去重

通過比較方法(compareTo方法)的返回值是否為0來判斷元素是否重複