HashCode和HashSet
当对象存储到Hash集合里是,应该重写该对象所在类的hashcode方法,如果不用储存到hash集合中则可以不重写hashcode方法。重写的原则是:当x.equals(y)时,它们所对应的hashcode也应该相等,即:x.hashcode()==y.hashcode()为true。
一个HashSet的例子:
HashSet是一个无序不可以重复储存的集合。那么HashSet是如何判断两个对象是否重复呢?答案是靠它们的hashcode方法,如果对应的两个对象所返回的hashcode方法的值是相等的,则表明该两个对象“相等”。所以一般情况下,用户需要对要储存到HashSet的对象所在的类重写hashcode方法,而不是用继承自Object的hashcode方法,因为Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数(这一般是通过将该对象的内部地址转换成一个整数来实现的),一般不符合用户的需求。
要想在HashSet中知道对象的位置,就要先计算该对象的hashcode,然后与散列表的列表的总数取余,所得结果就是保存这个元素的列表的索引。
当一个对象被储存进HashSet集合后,就不能再修改这个对象中的那些参与计算hashcode值的属性了,否则对象修改后的hashcode与最初储存到HashSet的值不一致,在这种情况下,即使在contains方法中使用该对象的当前引用作为参数区HashSet集合中检索对象,也将返回不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。为什么会杀不了呢:因为,当集合调用remove方法的时候,会从对象得到hashcode,但是原先对象储存的时候所对应的hashcode不是现在的hashcode,所以定位的不是相同的对象,因此删除不了。
所谓内存泄露是指该对象已经不需要再用,但是一直占着内存空间。- package April;
-
- import java.util.Collection;
- import java.util.Date;
- import java.util.HashSet;
-
- public class HashSetTest {
- public static void main(String[] args) {
- Collection c = new HashSet();
- Date d = new Date();
- try {
- Thread.sleep(500);//控制时间
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- Person p1 = new Person("p1",23,d);
- Person p2 = new Person("p2",23,new Date());
- Person p3 = new Person("p3",23,new Date());
- c.add(p1);
- c.add(p2);
- c.add(p3);
- p1.setName("p4");
- c.remove(p1);
- System.out.println(c.size());//size的值依然是3
- }
- }
复制代码 |