hashSet中的equals方法和hashCode方法


分类: TW |
转自:http://blog.csdn.net/benjaminzhang666/article/details/9468487
没有重写equals
示例代码
-
//2.
验证唯一性,存入自定义元素 -
class
Person{ -
private String name; -
private int age; -
-
public static void sop(Object o){ -
System.out.println(o); -
} -
-
public Person(String intname, age){ -
this.name =name; -
this.age =age; -
} -
-
public void setName(String name){ -
this.name =name; -
} -
-
public String getName(){ -
return this.name; -
} -
-
public void setAge( intage){ -
this.age =age; -
} -
-
public int getAge(){ -
return this.age; -
} -
-
public String toString(){ -
return this.name+"::"+this.age; -
} -
}
测试代码:
-
class
HashSetDemoIII -
{
-
public static void sop(Object o){ -
System.out.println(o); -
} -
-
public static void main(String[] args){ -
HashSeths =new HashSet(); -
hs.add(new Person( "a1",11)); -
hs.add(new Person( "a2",12)); -
hs.add(new Person( "a3",13)); -
hs.add(new Person( "a2",12)); -
-
Iteratorit =hs.iterator(); -
while(it.hasNext()){ -
sop(it.next()); -
} -
} -
}
测试结果:
测试结果:
【结论】循环迭代结果:a2::12被打印了两次,说明重复的元素new
{3}. 为Person类重写equals()方法判定两个对象的内容是否一致
-
public
boolean equals(Object obj){ -
if(!(obj
instanceof Person)){ -
return false; -
} -
-
Personp =(Person)obj; -
-
//用来查看equals方法是否被调用 -
sop(this.name + ".......equals......."+p.name); -
//认为名字相同并且年龄一样大的两个对象是一个 -
return
this.name.equals(p.name) && this.age== p.age; -
}
测试结果:
【结论】循环迭代结果:a2::12被打印了两次,说明重复的元素new
同时equals没有被调用,说明仅仅重写equals方法没起到作用
【分析】HashSet在存储元素的时候,是先查看两个对象的哈希值是否一样的。
{3}【1】.
如果哈希值是一样,再调用元素对象的equals方法,查看两个对象的内容是否一样。
{1}. 如果equlas比较的值一样,说明两个对象相同,不能添加到HashSet对应的集合中。
{2}. 如果equlas比较的值不一样,说明两个对象不同,可以添加到HashSet对应的集合中
{3}【2】.
【本例分析】这个例子中,由于四个Person类的对象都是new出来的,所以没有重写的hashCode是调用本地方法产生的值,所以一定是四个不相同的hashCode值。hashCode值都不一样,equals方法不起作用。
(3). 重写HashCode方法
为避免内容重复的数据添加到HashSet集合中,就必须重写hashCode()方法。
[1]. hashCode的返回值设置为统一的数值:
示例代码:
-
public
int hashCode(){ -
System.out.println(this.name + "...hashCode"); -
return 60; -
}
打印结果:
重复的元素没有被添加进来。
【建议】不要将hashCode的返回值都设置成一样的。因为hashCode的值和内存地址有关,这样设置不科学
[2]. 根据比较的条件重写HashCode方法
-
public
int hashCode(){ -
sop(this.name + "......hashCode"); -
return this.name.hashCode() + 29*age; -
}
这种做法,同样可以避免HashSet集合中不会存入相同元素。
【两种方式的具体区别和详细过程见个人总结。】
(4). 重写hashCode和equals的时候,常犯的错误
[1]. 子类重写hashCode的时候,将方法名写错,写成hasCode
[2]. 子类重写equals的时候,将参数传错,本来应该是public boolean equals(Object obj){}却写成了public boolean equals(自定义类型自定义类型引用)。这样集合框架的底层不会调用这个重载的方法。
2.
HashSet总结
1). HashCode如何保证元素唯一性?
(1). 需要重写的方法
通过重写自定义类的hashCode()和equals( )两个方法来达到元素的唯一性保证。
(2). 方法重写之后,执行的顺序
[1]. 如果元素的hashCode值相同,才会使用equals()方法进行判断。
[2]. 如果元素的hashCode值不同,不会调用equals()方法。
2). 开发中的建议
(1). 自定义对象,一定要重写hashCode和equals两个方法
【注意】开发中重写这两个方法,方便集合框架的底层调用这些方法。
(2). 建立高效的hashCode会使得hashSet添加元素的过程更为高效。
3). HashSet判断和删除元素的依据
示例代码:
-
public class HashSetDemoIV { -
public static void main(String[] args) { -
HashSeths =new HashSet(); -
hs.add(new Person( "a1",11)); -
hs.add(new Person( "a2",12)); -
hs.add(new Person( "a3",13)); -
System.out.println("hashSet中的元素:"+ hs); -
-
System.out.println("************************"); -
System.out.println("HashSet的 contains依据:" +hs.contains( newPerson( "a1",11))); -
-
System.out.println("************************"); -
System.out.println("HashSet的 remove依据:" +hs.remove( newPerson( "a3",13))); -
System.out.println("************************"); -
System.out.println("hashSet中的元素:"+ hs); -
} -
}
打印结果:
可以看出,hashSet在删除和判断元素的时候,依据的仍然是hashCode和equals这两个方法。
结论:
[1].
[2].