A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张振纲 中级黑马   /  2012-8-7 16:55  /  2149 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在HashSet中
主要通过
hashcod()和equals()这两个方法来判断存入的元素是否相同
首先通过哈希值比较
然后再用equals()

我想问的是,我们在设计程序的时候就已经尽可能使每个对象的哈希值不同
那么会不会调用equals方法

如果不调用的话那复写equals方法又有什么其他用处?

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
据说java在HashCode算法方面,有很大几率出现相同的情况
回复 使用道具 举报
程序是我们写的没错
我想问的是,我们在设计程序的时候就已经尽可能使每个对象的哈希值不同
这句话有问题,我们写程序其实就是写方法,用户通过简单的操作来实现
如果对象是由用户添加的,那么这些对象的哈希值,我们怎么能确定不同?
他们要是传入相同的对象呢?

传入对象不一定是我们传入的了,是由用户添加的对象,那么他们就有可能添加了重复的对象
如果没有这个判断的话,就会出现重复
那么我们所写的软件安全性也不高

所以equals是必须得有的
回复 使用道具 举报
马州州 发表于 2012-8-7 17:01
程序是我们写的没错
我想问的是,我们在设计程序的时候就已经尽可能使每个对象的哈希值不同
这句话有问题, ...

HashSet的实现是通过HashMap的KeySet做为存储结构的,大家都知道哈希算法为了避免键值冲突,一般有两个方法:二次哈希和链地址法。则HashMap就是用的链地址法。
public V put(K key, V value) {

        if (key == null)

            return putForNullKey(value);

       int hash = hash(key.hashCode());

        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table; e != null; e = e.next) {

            Object k;

            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

                V oldValue = e.value;

                e.value = value;

                e.recordAccess(this);

                return oldValue;

            }

        }


        modCount++;

        addEntry(hash, key, value, i);

        return null;

    }
看上面代码中下划线的黑体字,就是用hashCode()方法得到键值的桶(桶的概念是一个具有相同哈希值的容器)地址,然后才在一个桶中调用equals方法比较对象是否相等。

其实到这里我们已经知道了hashCode为什么一定要重写了。如果为两个实例即使equals方法成立,可是如果不在一个桶中,则都本不会调用equals方法比较了。

2011082413523665.png (501.8 KB, 下载次数: 26)

2011082413523665.png

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 很给力!

查看全部评分

回复 使用道具 举报
马州州 发表于 2012-8-7 17:01
程序是我们写的没错
我想问的是,我们在设计程序的时候就已经尽可能使每个对象的哈希值不同
这句话有问题, ...

我想楼主是不太清楚为什么我们定义一个类时要重写hashCode()方法和equals()方法。
首先在Object类里面有hashCode()和 equals()方法。
但是Object类里面的hashCode()是通过对象实例的来确定出这个对象实例的哈希码值的。同样Object类里面的equals()方法也是通过比较两个对象实例的地址值来确定对象是否相等的。所以默认情况下两个对象是通过比较引用值(也即地址值)是否相等来确定两个对象是否相等
但是如果我们自定义一个类,而又想根据对象里面的属性字段(成员属性)来比较两个对象是否相等的话,那么就需要在自定义的类中重写这两个方法了
比如我们定义一个person类,如果两个person对象的姓名和年龄相等 这两个对象就是相等的话  应该这样定义:
class Person
{
    private String name;
    private int age;
    public Person(String name , int age)
    {
        this.name=name;
        this.age=age;
    }
    public boolean equals(Object obj)  //重写Object类里面的equals方法
    {
       if( !(obj instanceof Person) )
           return false;
       Person p=(Person)obj;
       return this.name.equals(p.name)&&this.age==p.age;
    }
    public int hashCode()  //重写Object类里面的hashCode方法
    {
         return name.hashCode()+age*37;
    }
}
回复 使用道具 举报
牛杨 发表于 2012-8-7 17:30
我想楼主是不太清楚为什么我们定义一个类时要重写hashCode()方法和equals()方法。
首先在Object类里 ...

你说的这个我也知道啊,楼主问的是再确定hash值不同的情况下,可不可以不做equals比较
而不是问怎么比较的
回复 使用道具 举报
我想说的是,希望大家在回答问题的时候看一下楼主的需求,前面两位同学回答的很到位,但是我想说的是,真的不写equals程序也没有错,只是比较的时候会出问题,会出现重复,而不是程序不能运行
equals比较是为了加强程序的严谨性,而不是必须得覆盖,如果一个需求,允许出现重复元素,那么你还要复写equals么?
回复 使用道具 举报
无语,程序是你写的,你写程序干嘛?写出来不就是给别人用吗。别人在用你写的程序时,请问他知道吗????
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马