由于经常忘记关于hashset及hashmap中插入重复值时hashcode及equals的是怎样执行的,所以把一个例子记录下来来,省得以后忘记!首先引用老紫竹(java2000_net)的一个测试例子:
import java.util.HashSet;
import java.util.Set;
/**
* 老紫竹JAVA提高教程(2)-认识Set集合之HashSet。<br>
* Set用来保存不允许重复的数据。可以是任何对象类型。<br>
* JDK5以后,主类型可以通过autobox 放入Set里面。
*
* @author 老紫竹 JAVA世纪网(java2000.net)
*
*/
public class lession1 {
public int age;
public String name;
public static void main(String[] args) {
// 测试HashSet的特殊性
testForHashSet();
}
/**
* 专门针对HashSet的测试。
*/
public static void testForHashSet() {
System.out.println("----- testForHashSet -----------");
HashSet set = new HashSet();
// 增加一个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);
System.out.println("1----");
set.add(new lession1());
System.out.println("2----");
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看看
// 并没有增加,因为是重复的
System.out.println("---");
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());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
System.out.println("lession hashcode "+result);
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("lesson equals");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final lession1 other = (lession1) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
/**
* @author Administrator
*
*/
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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
System.out.println("hashCode"+result);
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final MyObject other = (MyObject) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
执行结果:
----- testForHashSet -----------
1
1
hashCode-582794785
1----
lession hashcode 961
2----
hashCode3064305
4
hashCode3064305
true
hashCode-337761603
5
---
hashCode-337761603
5
hashCode-337761603
equals
5
hashCode-337761572
false
hashCode-337761572
6
从结果集中不难看出每在hashset中增加一个对象,就会执行一次hashcode。所以判断两个对象是否重复首先得判断hashcode是否相等。如果不相等则说明是两个不同的对象,可以插入。
那hashcode相等的情况下怎么判断是否重复呢?
满足如下条件之一即可:
条件1:插入的引用的是同一个对象且equals 相等。比如上例中的
// 我们构造一个新的对象,内容和前面的相同
obj = new MyObject("java2000_net", 2);
set.add(obj);
条件2:插入同一个引用。比如上例中的
obj = new MyObject("java2000_net", 2);
set.add(obj);
set.add(obj);
此外这个例子还能说明一个问题:
如果是第二种插入
obj = new MyObject("java2000_net", 2);
set.add(obj);
set.add(obj);
则不会进行euqals比较,直接认为是重复。相当于==成立,如果在第二次插入之间改变某一属性则可能会导致hashcode改变则直接可以插入,就如上例子中最后一些代码
// 我们修改一下obj里面的年龄,再看看
obj.setAge(3);
// 我们再测试看看是否包含此对象。
// 请注意,我们这个obj和前面的obj是同一个对象
// 我们仅仅修改了一下我们的年龄
System.out.println(set.contains(obj));
// 我们尝试把obj再次放入set看看
// 我们又增加了长度
set.add(obj);