1、Set是Collection接口的子接口,其特性如下:
1) 元素是無序的。
2) 元素不重複。當添加重複的元素時,會采用屏蔽技術屏蔽掉。
3) 它的常用實作類為: HashSet。
案例1:驗證Set中的元素是否重複有序。
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set s1 = new HashSet();
//驗證元素是否有序
s1.add("a1");
s1.add("a321");
s1.add("a5");
s1.add("a3");
s1.add("a213");
s1.add("a6");
s1.add("a132");
s1.add("a2");
s1.add("a4");
System.out.println(s1 + " 注意元素是否有序!");
//驗證元素是否重複
s1.add("a4");
System.out.println(s1 + " 注意元素是否重複!");
}
}
結果:
[a132, a321, a1, a2, a3, a4, a213, a5, a6] 注意元素是否有序!
[a132, a321, a1, a2, a3, a4, a213, a5, a6] 注意元素是否重複!
結論1:Set中的元素不重複。當添加重複的元素時,會采用屏蔽技術屏蔽掉。
2、Set的實作類HashSet的特性:
1) 元素是無序的。
2) 元素不重複。當添加重複的元素時,會采用屏蔽技術屏蔽掉。
3) 判斷元素相等依賴equals()方法,同時,它還依賴hashCode()方法。
案例2:向HashSet實作類相關的容器中添加自定義類的對象來驗證HashSet的第三點特性。
import java.util.HashSet;
import java.util.Set;
public class SetTest1 {
public static void main(String[] args) {
Set s1 = new HashSet();
// 驗證HashSet實作類在判斷元素相等時,依賴什麼方法
s1.clear(); // 清空容器
s1.add(new Flower("a1", 9.9));
s1.add(new Flower("a4", 7.8));
s1.add(new Flower("a3", 6.9));
s1.add(new Flower("a2", 11.0));
System.out.println("s1>>>" + s1);
// 加入一個相同的對象試試有用不
s1.add(new Flower("a4", 7.8));
System.out.println("s1>>>" + s1);
}
}
class Flower {
private String name;
private double price;
public Flower(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "花名:" + name + " 花價:" + price;
}
}
結果:
s1>>>[花名:a4 花價:7.8, 花名:a3 花價:6.9, 花名:a1 花價:9.9, 花名:a2 花價:11.0]
s1>>>[花名:a4 花價:7.8, 花名:a3 花價:6.9, 花名:a4 花價:7.8, 花名:a1 花價:9.9, 花名:a2 花價:11.0]
結果與結論1沖突。是結論1錯了嗎?先不要下結論這麼快。
判斷元素重複必然要比較元素,對象比較相等用equals()方法。
是以,重寫Flower的equals()方法試試?
修改後的案例2:
import java.util.HashSet;
import java.util.Set;
public class SetTest1 {
public static void main(String[] args) {
Set s1 = new HashSet();
// 驗證HashSet實作類在判斷元素相等時,依賴什麼方法
s1.clear(); // 清空容器
s1.add(new Flower("a1", 9.9));
s1.add(new Flower("a4", 7.8));
s1.add(new Flower("a3", 6.9));
s1.add(new Flower("a2", 11.0));
System.out.println("s1>>>" + s1);
// 加入一個相同的對象試試有用不
s1.add(new Flower("a4", 7.8));
System.out.println("s1>>>" + s1);
boolean flag = s1.contains(new Flower("a3", 6.9));
System.out.println(flag ? "找到了。" : "沒找到。"); //這裡應該輸出沒找到的
}
}
class Flower {
private String name;
private double price;
public Flower(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Flower) {
Flower f = (Flower) obj;
Double d1 = price; // 對于double類型的數進行比較,最好轉換為對象後再進行比較,以防出錯
Double d2 = f.price;
if (name.equals(f.name) && d1.equals(d2)) {
return true;
}
return false;
}
return false;
}
@Override
public String toString() {
return "花名:" + name + " 花價:" + price;
}
}
結果:
s1>>>[花名:a4 花價:7.8, 花名:a3 花價:6.9, 花名:a1 花價:9.9, 花名:a2 花價:11.0]
s1>>>[花名:a4 花價:7.8, 花名:a3 花價:6.9, 花名:a4 花價:7.8, 花名:a1 花價:9.9, 花名:a2 花價:11.0]
沒找到。
還是與預想中的結果不一樣。這是為何?
通過查找資料,得知:
在java語言中,每一個對象都有一個哈希編碼(是一個整數),它由系統自動配置設定。
在Java語言中,規定:相等的對象應該擁有相同的哈希編碼。
HashSet中比較的對象還需要重寫hashCode()方法。
再次修改後的案例2:
import java.util.HashSet;
import java.util.Set;
public class SetTest1 {
public static void main(String[] args) {
Set s1 = new HashSet();
// 驗證HashSet實作類在判斷元素相等時,依賴什麼方法
s1.clear(); // 清空容器
s1.add(new Flower("a1", 9.9));
s1.add(new Flower("a4", 7.8));
s1.add(new Flower("a3", 6.9));
s1.add(new Flower("a2", 11.0));
System.out.println("s1>>>" + s1);
// 加入一個相同的對象試試有用不
s1.add(new Flower("a4", 7.8));
System.out.println("s1>>>" + s1);
boolean flag = s1.contains(new Flower("a3", 6.9));
System.out.println(flag ? "找到了。" : "沒找到。");
}
}
class Flower {
private String name;
private double price;
public Flower(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Flower) {
Flower f = (Flower) obj;
Double d1 = price; // 對于double類型的數進行比較,最好轉換為對象後再進行比較,以防出錯
Double d2 = f.price;
if (name.equals(f.name) && d1.equals(d2)) {
return true;
}
return false;
}
return false;
}
@Override
public int hashCode() {
return 123; // 我讓每個對象的哈希編碼都一樣,這樣比較起來就和hashCode沒關了
// return name.hashCode()+new Double(price).hashCode(); //這是更标準的寫法
}
@Override
public String toString() {
return "花名:" + name + " 花價:" + price;
}
}
結果:
s1>>>[花名:a2 花價:11.0, 花名:a3 花價:6.9, 花名:a4 花價:7.8, 花名:a1 花價:9.9]
s1>>>[花名:a2 花價:11.0, 花名:a3 花價:6.9, 花名:a4 花價:7.8, 花名:a1 花價:9.9]
找到了。
結論: 在HashSet實作類中,自定義類的對象比較相等必須重寫 equals()和hashCode()兩個方法。
注意: 在java語言中,每一個對象都有一個哈希編碼(是一個整數),它由系統自動配置設定。
在Java語言中,規定:相等的對象應該擁有相同的哈希編碼。