zoukankan      html  css  js  c++  java
  • 关于equals、hashcode和集合类的小结

    一.首先明确一点:equals()方法和hashcode()方法是Object类里的方法

      查看源码可以知道,在Object类中equals(obj)方法直接返回的是  this == obj 的值。对于引用变量来说,这个式子判断的是变量中存储的内存地址是否一致。而hashcode()方法的出现,目的是为了提高哈希表的性能,也就是说,提供这样一个方法是为了提高依据hashcode进行存取的数据结构的性能的。

     两者的关系:

     在Object类的注释中可以看到两个原则:

     两个类如果通过equals()方法比较返回的值为true,则这两个类调用hashcode()方法返回的整数值必须相等。

     两个类如果通过equals()方法比较返回的值为false,则这两个类调用hashcode()方法返回的整数值建议不同(hashcode的初衷),可以相等。

       故在Object类中:

     equals()方法比较的方式是比较两个引用的内存地址,对于任何新 new 出来的对象来说,他们的内存地址都是不一样的。而Object类默认的hashcode计算方式和类的内存地址相关,所以他们的hashcode是不同的。

          

    package com.njsteel.test;
    
    public class Test {
        public static void main(String[] args){
            
            Object obj1 = new Object();
            Object obj2 = new Object();
            Object obj3 = obj1;
            
            obj1.hashCode();//14576877
            obj2.hashCode();//12677476
            obj3.hashCode();//14576877
            
            obj1.equals(obj2);//false
            obj1.equals(obj3);//true        
        }
    }

      故,我们自定义的所有类,如果没有重写equals()方法和hashcode()方法,则都是满足上述的情况的。因为自定义的类都是Object类的子类。

    二. 其次,Java提供的很多便捷类都会重写equals()和hashcode()方法。

       这里只说明一下String类的情况。

         为什么String类要重写equals()和hashcode()方法?

         一般来说,当我们想判断两个String类对象的内容是否相同时,我们就会调用equals()方法,这是API文档告诉我们的。我们比较时,一般是两个不同对象的引用。这时候,即使String对象的内容相同,如果按照Object类里equals()的判断方法判断,返回的值始终都是false。

        所以为了满足这样的需要,String类equals()方法重写添加了根据内容判断两个String对象内容是否相同的逻辑代码。

        equals()被重写后,hashcode()自然也要被重写,因为重写的equals()方法破坏了Object类中规定的两者的关系。于是String类里的hashcode()方法也重写成了和String内容相关的样子。以满足原来的关系。

        其他的类就可以按照这样的情况以此类推。。

    三. 和某些集合类的关系

        先说Set:

        在看书的时候,对于Set的描述有:Set集合不允许包含相同的元素

        在Set里,相同的元素是指通过equals()方法返回值为true的两个对象。在调用Set的add()方法时,就会进行这个判断(add进来的元素会与Set集合里已经有的所有元素进行equals判断,如果有相同,则add()方法返回false,添加失败)。

      对于HashSet类:

      HashSet是Set接口的一个实现,自然也是不允许包含相同的元素。不过判断的方法和原始的Set有点不同。

      往HashSet集合里添加元素时,它不仅会通过equals()方法判断,还要调用hashcode()方法判断。只有当两个元素equals相等,并且hashcode也相等时,两个元素才是相同的元素。当其中有一个方法比较显示两个元素不一样时,HashSet会将其添加。

       对于HashMap类:

       我们知道HashMap的Key值是不能重复的。其实HashMap的Key值是保存在一个Set()集合里的。所以,作为Key,至少他们的hashcode是不相同的。如果两个对象是相同的Key(equals相等,hashcode也相同),值会覆盖。

    验证代码:

    package com.njsteel.test;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    public class HashSetTest {
        public static void main(String[] args){
            Set<MyString> set_1 = new HashSet<MyString>();
            MyString myString1 = new MyString(); 
            MyString myString2 = new MyString(); 
            //添加一个元素
            set_1.add(myString1);
            //添加一个equals返回true,但是hashcode不同的元素
            System.out.println(myString1.equals(myString2)+"!!!"+myString1.hashCode()+"/"+myString2.hashCode());
            System.out.println(set_1.add(myString2));//true,添加成功。
            
            
            //添加一个元素   
            Set<MyTestObject> set_2 = new HashSet<MyTestObject>();
            set_2.add(new MyTestObject());
            //添加一个equals返回false,但是hashcode相同的元素。
            System.out.println(set_2.add(new MyTestObject())+""+set_2.size());
            
            Map<MyString,String> map = new HashMap<MyString,String>();
            
            map.put(myString1, "1");
            map.put(myString2, "2");
            for(Object key : map.keySet()){
                System.out.println(map.get(key));
            }
    
        }
    }
    
    class MyString{
        
        @Override
        public boolean equals(Object obj) {
            // TODO Auto-generated method stub
            return true;
        }
    
        @Override
        public int hashCode() {
            // TODO Auto-generated method stub
            return super.hashCode();
        }
        
        
    }
    
    class MyTestObject{
    
        @Override
        public boolean equals(Object obj) {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public int hashCode() {
            // TODO Auto-generated method stub
            return 1;
        }
        
    }
     
     欢迎讨论指正。。
  • 相关阅读:
    VS 2010 制作 Windows Service 安装包
    Postback 之后保持浏览器滚动条的位置
    Stream之list转map及问题解决
    List.sort()排序功能
    The content of element type "resultMap"
    MyBatis 一对一,一对多,多对多
    Java Array、List、Set互相转化
    Java流(Stream)操作实例-筛选、映射、查找匹配
    JAVA系列笔记十八之nohup实现后台运行程序
    VSCode汇总
  • 原文地址:https://www.cnblogs.com/derry9005/p/3755745.html
Copyright © 2011-2022 走看看