天天看點

接口Set的特性及其實作類1、Set是Collection接口的子接口,其特性如下:2、Set的實作類HashSet的特性:

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語言中,規定:相等的對象應該擁有相同的哈希編碼。