HashSet和HashCode的关系


 

       今天在黑马论坛有个哥们说自己对equals和hashcode不同的重写玩了一下,重写前一个方法,重写后一个方法,两个都重写,两个都不写。结果发现给搞晕了= =问别人HashSet的执行过程究竟是咋样的。

       自己想了下,回忆了一下视频上说的,也自己测试了下。首先equals方法必须重写,Object那个默认的只是比较两个对象是否引用相同。至于Hashcode需不需要重写,我一开始觉得似乎不用。因为HashSet首先是看你存放的那个对象Hashcode是多少,然后再根据HashCode分若干个区域,最后用要存放的那个对象和那个对象所在区域的其他对象用equals对比。我当时觉得他们要是只重写equals方法,那么存放的时候都是调用父类的Hsahcode方法,照理应该是相同的。但是测试的时候发现错了,也就是说父类方法的HashCode并不是返回相同的值。于是进去看源码,调用本地方法,不懂。但猜想的应该没错。但就算是不同的HashCode,要是数字接近的话,也很有可能会存放在同一区域,那么就会重复,不能放了。以下代码演示了这种情况的发生:

public class HashCodeTest {

    public static void main(String[] args) {

       Set set = new HashSet();

       for(int i=0; i<10000; i++) {

           set.add(new HashPoint(2,2));

       }

       System.out.println(set.size());    

    }

}

 

class HashPoint {

    private int x;

    private int y;

    public HashPoint(int x ,int y) {

       this.x = x;

       this.y = y;

    }

    @Override

    public boolean equals(Object obj) {

       if (this == obj)

           return true;

       if (obj == null)

           return false;

       if (getClass() != obj.getClass())

           return false;

       HashPoint other = (HashPoint) obj;

       if (x != other.x)

           return false;

       if (y != other.y)

           return false;

       return true;

    }

}


输出的值固定为9998,也就是说有两个对象的hashcode因为跟已经存放进来的对象hashcode接近,所以存放的区域相同,这样一调用equals方法,相同,不能放。所以才出现那么个数值。而数值是固定的,所以说那个本地方法不是随机得到hashcode的,也不是动态获得的。另外在HashSet里面,一旦把对象的引用存进去了,那么这个对象equals用什么字段作参考,就不要修改什么字段。比如equals方法比较的是两个人的岁数,那么hsahcode的方法一定是根据岁数计算的,所以在存放了对象引用进去HashSet里面后,不要更改。一旦更改了,再删除的时候HashSet会根据它改变了的Hsahcode寻找符合条件的一个区域(与原来区域可能相同,也可能不同),因此当计算出该区域的范围后再查找要移走的引用,却发现没有在里面,这会造成内存泄露。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值