集合在Java裡面的作用非凡,我們常用的有Set,List和Map三種,我們先熟悉一下Set ,特別是HashSet的使用
package collection.lession2;
import java.util.HashSet;
import java.util.Set;
/**
* 老紫竹JAVA提高教程(2)-認識Set集合之HashSet。<br>
* Set用來保存不允許重復的數據。可以是任何對象類型。<br>
* JDK5以後,主類型可以通過autobox 放入Set裡面。
*
* @author 老紫竹 JAVA世紀網(java2000.net)
*
*/
public class Lession2 {
public static void main(String[] args) {
// 普通測試
testNormal();
// 測試HashSet的特殊性
testForHashSet();
testForHashSet2();
}
/**
* 測試保存混合類型的數據.
*/
public static void testNormal() {
System.out.println("----- testNormal -----------");
// Set有多個實現,我們先看看最常用的HashSet
Set set = new HashSet();
// 添加一個字符串
set.add("字符串");
// 添加一個整數對象
set.add(new Integer(1));
// 利用JDK5的特性,增加一個浮點數
set.add(123.45);
// 我們看看集合裡對象的數量
System.out.println(set.size());
// 我們嘗試增加一個重復的字符串
set.add("字符串");
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
// 我們來測試看看是否集合裡包含了某個數據
System.out.println(set.contains(123.45));
// 我們從裡面把這個浮點數刪除
set.remove(123.45);
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
}
/**
* 專門針對HashSet的測試。
*/
public static void testForHashSet() {
System.out.println("----- testForHashSet -----------");
HashSet<MyObject> set = new HashSet<MyObject>();
// 增加一個null對象
set.add(null);
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
// 再次增加一個null看看
set.add(null);
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
MyObject obj = new MyObject("java2000", 2);
set.add(obj);
obj = new MyObject("csdn", 10);
set.add(obj);
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
// 判斷是否包含某個對象
System.out.println(set.contains(obj));
obj = new MyObject("java2000_net", 2);
set.add(obj);
// 我們再次看看集合裡對象的數量
System.out.println(set.size());
// 我們嘗試把obj再次放入set看看
// 並沒有增加,因為是重復的
set.add(obj);
System.out.println(set.size());
// 我們構造一個新的對象,內容和前面的相同
obj = new MyObject("java2000_net", 2);
set.add(obj);
System.out.println(set.size());
// 我們修改一下obj裡面的年齡,再看看
obj.setAge(3);
// 我們再測試看看是否包含此對象。
// 請注意,我們這個obj和前面的obj是同一個對象
// 我們僅僅修改了一下我們的年齡
System.out.println(set.contains(obj));
// 我們嘗試把obj再次放入set看看
// 我們又增加了長度
set.add(obj);
System.out.println(set.size());
}
/**
* 專門針對HashSet的測試2。
*/
public static void testForHashSet2() {
System.out.println("----- testForHashSet2 -----------");
HashSet<MyObject2> set = new HashSet<MyObject2>();
MyObject2 obj = null;
for (int i = 0; i < 3; i++) {
obj = new MyObject2("java2000" + i, i);
set.add(obj);
System.out.println(set.size());
}
}
}
class MyObject {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
MyObject(String name, int age) {
this.name = name;
this.age = age;
}
public boolean equals(Object obj) {
System.out.println("equals");
if (obj == null || !(obj instanceof MyObject)) {
return false;
}
MyObject o = (MyObject) obj;
return this.age == o.age && this.name.equals(o.name);
}
public int hashCode() {
int hashCode = name.hashCode() + String.valueOf(age).hashCode();
return hashCode;
}
}
class MyObject2 {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
MyObject2(String name, int age) {
this.name = name;
this.age = age;
}
public boolean equals(Object obj) {
System.out.println("equals");
if (obj == null || !(obj instanceof MyObject2)) {
return false;
}
MyObject2 o = (MyObject2) obj;
return this.age == o.age && this.name.equals(o.name);
}
public int hashCode() {
return 1;
}
}
class MyObject3 {
private int age;
private String name;
// 采用一個變量進行控制
// 一旦生成了hashCode,則不再變動
private int HASHCODE = Integer.MIN_VALUE;
public int hashCode() {
if (HASHCODE == Integer.MIN_VALUE) {
// 重新生成本類的hashCode
HASHCODE = name.hashCode() + String.valueOf(age).hashCode();
}
return HASHCODE;
}
}
說明,針對HashSet:
Set不允許重復
允許 null,重復的null只算一個
判斷是否存在一個數據(是否重復),先判斷其hashCode是否存在,若存在再逐個判斷 hashCode相同的數據是否相等
判斷是否相等,除了hashCode相等外,還要判斷對象引用相等(==),或者 equals
如果一個對象的hashCode變動了,會造成找不到這個對象,也就出現了內存洩漏的危 險。
hashCode 方法是HashSet裡面對象的關鍵,它的算法影響到了數據的分散和查找效率 。某個確認對象的hashCode不應該變動,避免出現內存洩漏,可以采用如下方法,來方式 屬性變化造成hashCode變化
class MyObject3 {
private int age;
private String name;
// 采用一個變量進行控制
// 一旦生成了hashCode,則不再變動
private int HASHCODE = Integer.MIN_VALUE;
public int hashCode() {
if (HASHCODE == Integer.MIN_VALUE) {
// 重新生成本類的hashCode
HASHCODE = name.hashCode() + String.valueOf(age).hashCode();
}
return HASHCODE;
}
}