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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王清云 黑马帝   /  2011-9-21 15:06  /  2742 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

今天在又碰到俩了,先用代码来说吧:
                     String s1="java01";
                String s4="java01";
                System.out.println(s1.hashCode()==s4.hashCode());
                System.out.println(s1.equals(s4));
                System.out.println(s1==s4);
如果是这样的话,这三个判断都是true,因为String这样创建是在栈中,所以此时s1和s4的值相等,通过API,我发现String的hashCode值的算法只喝String里面的值有关:
String 对象的哈希码根据以下公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为 0。)
这说明只要String里面的内容一样,hashcode就一样,而String的equals方法似乎和hashcode无关,源码里面equals方法是这样写的:[code=java]public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }[/code]主要是通过每一个字符的对比来判断是否相等。
java中的基本类型也对equals方法和hashcode方法进行重写了,所以这两个方法没有什么关联。
接着我从Object的源码中找到其equals方法:
public boolean equals(Object obj) {
        return (this == obj);
    }
也就是说,我们自己定义的类,如果没有重写equals方法,那么其结果和==是一样的。
今天看到hashset的时候,毕老师说,如果他们的hashcode一样,还会继续根据equals方法来判断其是否相同,原来没有重写的equals方法也是根据地址来判断的,难怪即使你把类的hashcode重写成都返回同样的值,hashset还是会判断出是否是同样的对象,因为地址是不能改变的:[code=java]public class HashDemo {
        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                HashDemo h1=new HashDemo();
                HashDemo h2=new HashDemo();
                System.out.println(h1.hashCode()==h2.hashCode());
                HashSet hs=new HashSet();
                hs.add(h1);
                hs.add(h2);
               
                Iterator it=hs.iterator();
                while(it.hasNext()){
                        System.out.println(it.next());
                }
               
        }

        @Override
        public int hashCode() {
                // TODO Auto-generated method stub
                return 110;
        }

       
       

}[/code]就像这样,即使返回的hashcode一样,但是仍然会add进hashset里面。
所以如果没有重写equals方法,自定义类里面的equals方法和==是一样的,而java中定义好的类大部分是有重写过equals方法的,所以这两个才会有时候出现区别。

不知道我这样分析的对不对,请大家指教。

评分

参与人数 1技术分 +1 收起 理由
wangfayin + 1

查看全部评分

5 个回复

倒序浏览
黑马网友  发表于 2011-9-21 16:33:21
沙发
就目前Java API中,如果hashCode相同,如果不重写equals方法,那么他们是equals的。好像怎么写都不出hashCode相同,equals为false的方法。[code]import java.util.HashSet;
import java.util.Iterator;

public class TestSet {
        /**
         * @param args
         */
        public static void main(String[] args) {
                Integer a = 10;
                Integer b = 10;
                HashSet hs = new HashSet();
                hs.add(a);
                hs.add(b);
                System.out.println(a.hashCode() == b.hashCode());
                System.out.println(hs.size());
                Iterator it = hs.iterator();
                while (it.hasNext()) {
                        System.out.println(it.next());
                }
                TestSet ts1 = new TestSet();
                TestSet ts2 = new TestSet();
                HashSet hs2 = new HashSet();
                hs2.add(ts1);
                hs2.add(ts2);
                System.out.println(ts1.hashCode() == ts2.hashCode());
                System.out.println(hs2.size());
                Iterator it2 = hs2.iterator();
                while (it2.hasNext()) {
                        System.out.println(it2.next());
                }
                System.out.println("---------------------------");
                String c = new String("abc");
                String d = new String("abc");
                HashSet hs3 = new HashSet();
                hs3.add(c);
                hs3.add(d);
                System.out.println(c.hashCode() == d.hashCode());
                System.out.println(c.equals(d));
                System.out.println(hs3.size());
                Iterator it3 = hs3.iterator();
                while (it3.hasNext()) {
                        System.out.println(it3.next());
                }
               
        }
}[/code]
回复 使用道具 举报
黑马网友  发表于 2011-9-21 17:12:41
藤椅

回复 沙发 的帖子

hashcode方法也可以重写啊。
回复 使用道具 举报
黑马网友  发表于 2011-9-21 22:00:35
板凳

==与equals的区别

==是用来判断数据存放的地址是否相同
equals是用来判断数据存放地址中的内容是否相同

评分

参与人数 1技术分 +2 收起 理由
wangfayin + 2 对哦!

查看全部评分

回复 使用道具 举报
黑马网友  发表于 2011-9-21 23:16:58
报纸
[quote] 原帖由 [i]张静[/i] 于 2011-09-21 22:00 发表 [url=http://bbs.itheima.com/redirect.jsp?goto=findpost&pid=10516&ptid=1650][img]http://bbs.itheima.com/images/common/back.gif[/img][/url]==是用来判断数据存放的地址是否相同
equals是用来判断数据存放地址中的内容是否相同 [/quote]
int a= 2;
int b=2;
那么 a==b 是false咯,不对的。
回复 使用道具 举报
黑马网友  发表于 2011-9-22 14:43:35
地板
如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。
如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马