集合: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來判斷元素是否重複