一:集合了解
(一)確定性,互異性,無序性
確定性:對任意對象都能判定其是否屬于某一個集合
互異性:集合內每個元素都是無差異的,注意是內容差異
無序性:集合內的順序無關
(二)集合接口HashSet,TreeSet,LinkedHashSet
–HashSet (基于散列函數的集合,無序,不支持同步)
–TreeSet (基于樹結構的集合,可排序的,不支持同步)
–LinkedHashSet(基于散列函數和雙向鏈表的集合,可排序的,不支持同步
二:HashSet
(一)基礎方法
–基于HashMap實現的,可以容納null元素, 不支持同步
Set s= Collections.synchronizedSet(newHashSet(...));
–add 添加一個元素
–clear 清除整個HashSet
–contains 判定是否包含一個元素
–remove 刪除一個元素 size 大小
–retainAll 計算兩個集合交集
(二)HashSet實現
HashSet hs = new HashSet(); //<>是泛型編程,類似于C++模板
hs.add(null);
hs.add(10000);
hs.add(22);
hs.add(1010);
hs.add(50001010);
hs.add(101035);
hs.add(3);
System.out.println(hs.size());if(!hs.contains(6)) {
hs.add(6);
}
System.out.println(hs.size());
hs.remove(4); //存在,則刪除,不存在,則不操作for(Integer item : hs) {
System.out.println(item);
}
7
8
null //無序性
10000
1010
3
22
6
50001010
101035
(三)性能測試:因為無序性,無索引操作。for效率高
public static void trverseByIterator(HashSeths) {//使用迭代器遍歷
System.out.println("==========迭代器遍歷===========");long startTime = System.nanoTime(); //獲取開始時間,以納秒為單位返回正在運行的Java虛擬機的高分辨率時間源的當前值。
Iterator iter = hs.iterator(); //獲取迭代指針
while(iter.hasNext()) {
iter.next();
}long endTime =System.nanoTime();long duration = endTime-startTime;
System.out.println("iterator使用納秒:"+duration);
}public static void trverseByFor(HashSeths) {//使用迭代器遍歷
System.out.println("==========for索引遍歷===========");long startTime = System.nanoTime(); //獲取開始時間,以納秒為單位返回正在運行的Java虛擬機的高分辨率時間源的當前值。
for(Integer item : hs) {
;
}long endTime = System.nanoTime(); //獲取開始時間,以納秒為單位返回正在運行的Java虛擬機的高分辨率時間源的當前值。
long duration = endTime-startTime;
System.out.println("for使用納秒:"+duration);
}
==========迭代器遍歷===========iterator使用納秒:5738665
==========for索引遍歷===========for使用納秒:2721950
(四)retainAll交集測試
//測試交集
HashSet hs1 = new HashSet();
HashSet hs2 = new HashSet();
hs1.add("a");
hs1.add("b");
hs1.add("c");
hs2.add("c");
hs2.add("d");
hs2.add("e");
hs1.retainAll(hs2);//將交集保存在hs1中
for(String item : hs1) {
System.out.println(item);
}
c
三:LinkedHashSet(與HashSet一致)
–繼承HashSet,也是基于HashMap實現的,可以容納null元素,按照插入順序有序
–不支持同步
Set s= Collections.synchronizedSet(newLinkedHashSet(...));
–方法和HashSet基本一致
add, clear, contains, remove, size
–通過一個雙向鏈表維護插入順序
四:TreeSet
(一)基本方法
–基于TreeMap實現的,不可以容納null元素,不支持同步
SortedSet s= Collections.synchronizedSortedSet(newTreeSet(...));
–add 添加一個元素
–clear 清除整個TreeSe
–contains 判定是否包含一個元素
–remove 刪除一個元素 size 大小
–根據compareTo方法或指定Comparator排序
(二)實現(有序,會自動排序,紅黑樹)
TreeSet ts = new TreeSet(); //<>是泛型編程,類似于C++模板
ts.add(1000);
ts.add(15300);
ts.add(100);
ts.add(3);
ts.add(566000);if(!ts.contains(4)) {
ts.add(4);
}
for(Integer item : ts) {
System.out.println(item);;
}
4
100
1000
15300
566000
(三)性能測試:for更加高效
==========迭代器遍歷===========iterator使用納秒:9246423
==========for索引遍歷===========for使用納秒:3366874
五:HashSet, LinkedHashSet, TreeSet對象比較(元素重復)《重點》
(一)HashSet和LinkedHashSet判定元素重復的原則
–判定兩個元素的hashCode返回值是否相同,若不同,返回false
–若兩者hashCode相同,判定equals方法,若不同,返回false;否則返回true。
–hashCode和equals方法是所有類都有的,因為Object類有
比較之前會先調用hashCode,之后是equals方法
1.正常執行,含重復
classDog{intage;public Dog(inta) {this.age=a;
}
}public classCompareTest {public static voidmain(String[] args) {
Dog d1=new Dog(10);
Dog d2=new Dog(10);
HashSet hs=new HashSet();
hs.add(new Dog(10));
hs.add(new Dog(1));
hs.add(new Dog(3));
hs.add(new Dog(10));
hs.add(new Dog(10));
System.out.println(hs.size());
}
}
5
Dog類本身沒有hashCode方法,繼承于Object,而Object類的hashCOde會返回對象信息和內存地址經過運算后的一個值。兩個不同對象,其值必然不一致
2.實現對象的hashCode方法和equals方法實現去重
import java.util.*;classDog{intage;public Dog(inta) {this.age=a;
}public intgetAge() {return this.age;
}public inthashCode() {
System.out.println("hashCode exec...");return this.age;
}publicboolean equals(Object obj2) {
System.out.println("equals exec...");if(0==this.age-((Dog)obj2).getAge())return true;else
return false;
}
}public classCompareTest {public static voidmain(String[] args) {
Dog d1=new Dog(10);
Dog d2=new Dog(10);
HashSet hs=new HashSet();
hs.add(new Dog(10));
hs.add(new Dog(1));
hs.add(new Dog(3));
hs.add(new Dog(10));
hs.add(new Dog(10));
System.out.println(hs.size());
}
}
hashCode exec...
hashCode exec...
hashCode exec...
hashCode exec...
equals exec...
hashCode exec...
equals exec...3 //去重實現
先執行hashCode,只有hashCode通過,才會執行equals方法
publicString toString() {
System.out.println("toString exec...");return age+"";
}
要保持equals,hashCode和toString三位一體。都應該各自相同
(二) TreeSet去重
添加到TreeSet,需要實現Comparable接口,即實現compareTo方法
與hashCode和equals無關,只與compareTo有關
import java.util.*;classDog implements Comparable{intage;public Dog(inta) {this.age=a;
}public intgetAge() {return this.age;
}public inthashCode() {
System.out.println("hashCode exec...");return this.age;
}publicboolean equals(Object obj2) {
System.out.println("equals exec...");if(0==this.age-((Dog)obj2).getAge())return true;else
return false;
}publicString toString() {
System.out.println("toString exec...");return age+"";
}public intcompareTo(Object obj2) {
System.out.println("compareTo exec...");return this.age -((Dog)obj2).getAge();
}
}public classCompareTest {public static voidmain(String[] args) {
Dog d1=new Dog(10);
Dog d2=new Dog(10);
TreeSet hs=new TreeSet();
hs.add(new Dog(10));
hs.add(new Dog(1));
hs.add(new Dog(3));
hs.add(new Dog(10));
hs.add(new Dog(10));
System.out.println(hs.size());
}
}
View Code
compareTo exec...
compareTo exec...
compareTo exec...
compareTo exec...
compareTo exec...
compareTo exec...
compareTo exec...
compareTo exec...3
可以知道,去重和hashCode與equals無關,不執行。而是直接去找compareTo方法
六:總結
(一)HashSet, LinkedHashSet, TreeSet的元素都只能是對象
會進行自動裝箱
(二)HashSet和LinkedHashSet判定元素重復的原則《重點》
–判定兩個元素的hashCode返回值是否相同,若不同,返回false
–若兩者hashCode相同,判定equals方法,若不同,返回false;否則返回true。
–hashCode和equals方法是所有類都有的,因為Object類有
(三)TreeSet判定元素重復的原則《重點》
–需要元素繼承自Comparable接口
–比較兩個元素的compareTo方法
(四)注意:對于基本類型的包裝類。本來就實現了compareTo接口和其他比較方法,所以HashSet,LinkedHashSet,TreeSet中對于包裝類是默認去重的