1. 概述
Set
接口中元素無序,並且都會以某種規則保證存入的元素不出現重複。
特點
- 不允許存儲重複的元素
- 沒有索引,沒有帶索引的方法,也不能使用普通的for循環遍歷
- Set集合取出元素的方式可以採用:迭代器、增強for。普通for不行!
Set
集合有多個子類,這裏我們介紹其中的HashSet
、LinkedHashSet
這兩個集合。
2. HashSet集合
java.util.HashSet
是Set
接口的一個實現類,它所存儲的元素是不可重複的,並且元素都是無序的(即存取順序不一致)。java.util.HashSet
底層的實現其實是一個java.util.HashMap
支持.
優點
- 具有良好的存取和查找性能:
HashSet
是根據對象的哈希值來確定元素在集合中的存儲位置。 - 元素唯一性:依賴於:
hashCode
與equals
方法。
特點
- 不允許存儲重複的元素
- 沒有索引,沒有帶索引的方法,也不能使用普通的for循環遍歷
- 是一個無序的集合,存儲元素和取出元素的順序有可能不一致
- 底層儲數據的結構:哈希表(查詢的速度非常的快)
代碼:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo01Set {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
// 使用迭代器遍歷set集合【不能用for循環,因爲沒有索引】
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
Integer n = it.next();
System.out.println(n); // 123
}
System.out.println("=========================");
// 增強for遍歷集合
for (Integer i : set) { // set.for
System.out.println(i);
}
}
}
結果:
根據結果我們發現數字1
只存儲了一個,也就是說重複的元素set集合不存儲。
1
2
3
=========================
1
2
3
3. HashSet存儲自定義類型元素
若想在HashSet集合中存放自定義的對象,那麼想要保證其唯一,就必須重寫hashCode和equals方法建立屬於當前對象的比較方式。
必須重寫hashCode和equals方法
創建自定義Person類
import java.util.Objects;
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//省略getterandsetter方法和構造器
}
測試類
public class Demo03HashSetSavePerson {
public static void main(String[] args) {
// 創建HashSet集合存儲Person
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("小明",18);
Person p2 = new Person("小明",18);
Person p3 = new Person("小明",19);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println("=================");
System.out.println(p1 == p2);
System.out.println(p1.equals(p2)); // 重寫equals之前比較的是地址值
System.out.println("=================");
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);
// 遍歷
for (Person p : set) {
System.out.println(p);
}
}
}
結果:
- 未重寫:
1355531311
1967205423
42121758
=================
false
false
=================
com.luis.demo03.Set.Person@50cbc42f
com.luis.demo03.Set.Person@282ba1e
com.luis.demo03.Set.Person@75412c2f
- 重寫後:
23458772
23458772
23458773
=================
false
true
=================
com.luis.demo03.Set.Person@165f3d5
com.luis.demo03.Set.Person@165f3d4
4. LinkedHashSet集合
在HashSet下面有一個子類java.util.LinkedHashSet
,它是**鏈表和哈希表(數組+鏈表/紅黑樹)**組合的一個數據存儲結構。可保證集合元素的有序。
演示代碼如下:
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Demo04LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set); // [abc, www, itcast] 無序的,不允許重複
System.out.println("==============");
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcast");
System.out.println(linked); // [www, abc, itcast] 有序的,不允許重複
}
}
結果:
[abc, www, itcast]
==================
[www, abc, itcast]