博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HashCode()与equals(),对象相等 讲解:
阅读量:2402 次
发布时间:2019-05-10

本文共 4036 字,大约阅读时间需要 13 分钟。

hashcode()是干什么用的:

hashCode 的常规协定是:

·        在 Java 应用程序执行期间,在同一对象上多次调用hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

·        如果根据 equals(Object)方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。

·        以下情况 是必需的:如果根据 方法,两个对象不相等,那么在两个对象中的任一对象上调用hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

 

Equals():注意:当此方法被重写时,通常有必要重写hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

其源代码:

public boolean equals(Object obj) {

return (this == obj);

注:判读两个对象是否相等;

总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。

      于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)    } 

在实际的应用当中你也许会重新equals() 方法,若不重新hashcoade()方法比如下面的程序:

publicclass HashObject 

    private String name = null; 
    public static int hascode = 0; 
    
    private int temp = 0; 
    
    public HashObject() 
    { 
       hascode++; 
        if(temp <= 0) 
        { 
           temp = hascode; 
        } 
    } 
    public String getName() 
    { 
        returnname; 
    } 
    public void setName(Stringname) 
    { 
       this.name = name; 
    } 
    
    @Override 
    public int hashCode() 
    { 
        returntemp; 
    } 
    
    @Override 
    public boolean equals(Objectobj) 
    { 
        returnhascode % 2 == 0; 
    } 
    public static void main(String[]args) 
    { 
       HashObject obj1 = new HashObject(); 
       obj1.setName("Lilei"); 
       HashObject obj2 = new HashObject(); 
       obj2.setName("Hanmeimei"); 
        
       Map<HashObject,HashObject> test = new HashMap<HashObject,HashObject>(); 
       test.put(obj1, obj1); 
       test.put(obj2, obj2); 
       test.get(obj1); 
       System.out.println("equals is " + obj2.equals(obj1)); 
       System.out.println("obj2's hashCode = " + obj2.hashCode()); 
       System.out.println("obj1's hashCode = " + obj1.hashCode()); 
       System.out.println(test.get(obj1)); 
       System.out.println(test.get(obj2)); 
        
       Set<HashObject> set = new HashSet<HashObject>(); 
       set.add(obj1); 
       set.add(obj2); 
       System.out.println(set); 
    } 
    
    @Override 
    public String toString() 
    { 
        return"HashObject.toString():" + getName() + " HashCode = " +hashCode(); 
    } 
运行结果: 
equals is true 
obj2's hashCode = 2 
obj1's hashCode = 1 
HashObject.toString():Lilei HashCode = 1 
HashObject.toString():Hanmeimei HashCode = 2 
[HashObject.toString():Lilei HashCode = 1,HashObject.toString():Hanmeimei HashCode = 2]

 

是可以出现equals()相等 到hashcode 不相同,但是会发生如下

例子:equals相等但是hashcode不等(即重写了equals不重写hashcode方法的坏处):

Set<A> set = new HashSet<A>();
set.put(a1);
set.put(a2);
如果a1.equals(a2)返回true,那么我们认为“a1和a2即为同一对象”,把它两放到set中去就只能存下一个对象,因为Set不允许重复的对象。Set存元素时使用对象的hashCode决定存储的位置,这样调用a1和a2的hashCode()方法时两个hashCode值不相等,存储的位置不一样,也就没了覆盖,这时候调用set.size()得到2,而不是1,出现错误。

HashMaP get() 源代码:

public V get(Objectkey) {

        if (key == null)

            return getForNullKey();

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

        for (Entry<K,V> e = table[indexFor(hash,table.length)];

             e != null;

             e = e.next) {

            Object k;

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

                return e.value;

        }

        return null;

}

 

 

    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[i]; 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;

    }

根据他们的hash 值是否相等,还有内存是否相同,或者是否equals;

然而String,对hashcode进行重写

public int hashCode() {

    int h = hash;

    if (h == 0) {

        int off = offset;

        char val[] = value;

        int len = count;

 

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

                h =31*h + val[off++];

            }

            hash = h;

        }

        return h;

    }

 

String a = new String("adc");

        String b = new String("adc");

        System.out.println(a.hashCode()==b.hashCode());//true

       System.out.println(a==b);//false

总结:可以发现对象不同,hashcode 一样;对象一样hashcode 一样;equals 相同,hashcode相同,equals不同,hashcode 不一定不同也许相同,比如string类中没覆盖equal方法

转载地址:http://kppob.baihongyu.com/

你可能感兴趣的文章
javascript动态隐藏显示技术(转)
查看>>
硬盘主引导记录详解(转)
查看>>
安装J2SE 1.3.1 for Linux的方法(转)
查看>>
Apche日志系列(5):高级技术(转)
查看>>
谈谈数据从sql server数据库导入mysql数据库的体验(转)
查看>>
关联查询子查询效率简单比照
查看>>
linux启动盘制作
查看>>
职业经理人影响力自检手册(二)
查看>>
企业如何提好自己的内部需求?
查看>>
[分享]ERP实施工程师笔试题目
查看>>
最美的七十个英语单词
查看>>
中国企业需要精益求精 (zt)
查看>>
第四章 计划工作概述
查看>>
物流基础知识(八)
查看>>
关于BPR和ERP的关系思考 (转载)
查看>>
写作必背200句
查看>>
职业经理人影响力自检手册(一)
查看>>
[HR规划]如何在中小企业进行人力资源规划(zt)
查看>>
ERP实施先要解决人的问题(zt)
查看>>
有效库存:供应链产业切肤之痛 (zt)
查看>>