------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------
Set 接口特點:
不允許存儲重複元素,無序集合:存儲取出沒有順序(不保證迭代順序),沒有索引
Set接口方法,和父接口Collection抽象方法完全一樣
Set接口存儲對象並迭代,找實現類HashSet集合
HashSet 如何保證元素唯一?
Set裏的元素是不能重複的,使用 equals() 方法和 hashCode() 方法來區分重複與否。覆蓋 equals() 方法、hashCode() 方法用來判斷兩個對象是否爲同一對象,而“==”判斷地址是否相等,用來決定引用值是否指向同一對象。
底層數據結構是哈希表,哈希表依賴於哈希值存儲,添加功能底層依賴於兩個方法 inthashCode(), boolean equals(Object obj) ,當存儲對象時,先調用對象的 hashCode() 方法,校驗哈希值是否與哈希表中已存在對象的哈希值相等,如果相等,當前對象調用 equals() 方法與表中已存在對象進行比較,如果結果是 true ,則哈希值一樣,且比較結果爲 true ,集合判斷爲同一對象不再存儲。
如果兩個對象,哈希值一樣,equals一定返回 true 嗎?不一定
如果兩個對象,equals方法返回 true,擁有相同的哈希值嗎?一定
HashSet特性:無序,不重複,無索引
底層數據結構是哈希表:數組 + 鏈表實現(元素是鏈表的數組)
存取速度都非常快,線程不安全集合,運行速度快
HashMap 和 HashSet 有什麼關係?
HashSet 底層是採用 HashMap 實現的。
privatetransient HashMap<E, object> map;
HashSet 類裏面定義的一個私有成員變量。放進 HashSet 中的對象,其實是用這個HashMap 的 key 來存儲的。當調用 HashSet 的 add 方法時,實際上是向 HashMap 中增加了一行 (key-value) 對,該行的 key 就是向 HashSet 增加的那個對象,該行的 value 就是一個 Object 類型的常量(靜態的 Object 對象)。
LinkedHashSet特點:元素有序(由鏈表保證)唯一(由哈希表保證)
since JDK1.4 ,出現時間晚於 Set 接口和父類 HashSet
繼承 HashSet
存儲和取出的順序是一致的
底層結構是基於哈希表的鏈表實現
線程不安全集合
Set 接口是無序的集合,而LinkedHashSet 變成有序集合。
TreeSet 集合的自身特性:
底層數據結構是紅黑樹(自平衡的二叉樹),保證元素的排序和唯一性
線程不安全,運行速度快
對存儲的對象進行排序:
自然順序排序
(java.lang.Comparable,對實現類的對象進行強制排序)
自定義的對象的類 implementsComparable<> ,
重寫接口中的 compareTo() 方法,建立自定義對象的自然順序
根據創建集合時傳遞的比較器進行排序
自定義比較器 implements Comparator<> ,
重寫接口中的 compare() 方法
TreeSet存儲自定義對象
TreeSet集合存儲對象時,不考慮hashCodeequals
1. TreeSet集合依據對象的自然順序進行排序
要求存儲到TreeSet集合中的對象,具有自然順序
類實現Comparable接口,重寫compareTo
2.TreeSet集合自己具備比較性
自定義比較器對象,實現java.util.Comparator,重寫compare
接口實現類對象,傳遞給TreeSet集合
一旦有了比較器,TreeSet集合不考慮對象自然順序
HashSet 集合存儲自定義對象並遍歷(如果對象的成員變量值相同即爲同一個對象)
package cn.itcast.set;
importjava.util.HashSet;
import java.util.Set;
/*
* HashSet存儲自定義對象,不存儲相同的元素
* 校驗對象的唯一性
* 依賴於在自定義對象中重寫hashCode 和 equals 兩個方法實現
*/
public classHashSetDemo {
public static void main(String[] args) {
Set<Person> set = new HashSet<>();
set.add(new Person("zs", 20));
set.add(new Person("ls", 21));
set.add(new Person("zs", 20));
for (Person person : set) {
System.out.println(person);
}
// Person [name=ls, age=21]
// Person [name=zs, age=20]
}
}
TreeSet 集合存儲自定義對象並遍歷
(如果對象的成員變量值相同即爲同一個對象,按照年齡進行從大到小進行排序)
package cn.itcast.set;
import java.util.TreeSet;
publicclassTreeSetDemo {
publicstaticvoid main(String[] args) {
TreeSet<String>set= newTreeSet<String>();
set.add("www");
set.add("itcast");
set.add("cn");
for (String string : set) {
System.out.print(string + " ");
}
// cn itcast www 對存儲的對象進行排序
System.out.println();
// 自然順序比較
TreeSet<Person>set2= newTreeSet<Person>();
// 比較器比較
// TreeSet<Person>set2 = new TreeSet<Person>(new PersonComparator());
set2.add(new Person("zs", 20));
set2.add(new Person("ls", 21));
System.out.println(set2);
// [Person [name=ls, age=21], Person [name=zs, age=20]]
}
}
/*
* 重寫接口compareTo方法,建立Person類自然順序
*
* @seejava.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
publicint compareTo(Person o) {
intvalue = this.name.compareTo(o.name);
if (value == 0) {
returnthis.age - o.age;
}
returnvalue;
}
package cn.itcast.set;
import java.util.Comparator;
publicclassPersonComparator implements Comparator<Person>{
/*
* (non-Javadoc)
* @seejava.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
publicint compare(Person o1, Person o2) {
intvalue = o1.getAge() - o2.getAge();
if (value == 0) {
returno1.getName().compareTo(o2.getName());
}
returnvalue;
}
}
鍵盤錄入 5 個學生信息,按照總分從高到低輸出到控制檯
package cn.itcast.set;
importjava.util.Scanner;
import java.util.Set;
importjava.util.TreeSet;
public class SetTest1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Set<StudentInfo> set = new TreeSet<StudentInfo>(new StudentScoreComparator());
for (int i = 0; i < 3; i++) {
String line = sc.nextLine();
String[] str = line.split(" +");
StudentInfo s = new StudentInfo(str[0],Integer.parseInt(str[1]), Integer.parseInt(str[2]),
Integer.parseInt(str[3]));
set.add(s);
}
for (StudentInfo studentInfo : set) {
System.out.println(studentInfo);
}
}
}
package cn.itcast.set;
import java.util.Comparator;
publicclassStudentScoreComparator implements Comparator<StudentInfo> {
@Override
publicint compare(StudentInfo o1, StudentInfo o2) {
intvalue = o1.getTotal() - o2.getTotal();
returnvalue == 0 ? o1.getName().compareTo(o2.getName()) : value;
}
}