• Object类中“==”与“equals()”的区别 and HastSet的hashcode()


    1. "=="与"equals()"的区别

    1.1 区别

    • 对于基本数据类型而言, =比较的是值是否相等,对引用数据类型而言,== 比较的是变量指向的地址是否相等
    • Object类当中的equals()方法,比较的是引用数据类型所指向的地址是否相等,无法比较基本数据类型
    • String类当中重写了equals()方法,先比较地址是否相等,如果相等,返回true,不相等,比较值是否相等

    1.2 列举例子

    class Person{
        int a;
        Person(int a){
            this.a = a;
        }
    }
    
    public class Test {
        
        public static void main(String[] args) {
            int a = 1;
            int b = 1;
            System.out.println(a == b);// 比较值
            System.out.println("--------");
            Person ap = new Person(1);
            Person bp = new Person(2);
            System.out.println(ap == bp);	// 比较地址
            System.out.println(ap.equals(bp));	// 调用obj的equals()
            System.out.println("--------");
            bp = ap;
            System.out.println(ap == bp);
            System.out.println(ap.equals(bp));
            System.out.println("--------");
            String as = "123";
            String bs = "123";
            System.out.println(as == bs);
            System.out.println(as.equals(bs));
            System.out.println("--------");
            bs = new String("123");
            System.out.println(as == bs);
            System.out.println(as.equals(bs));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    输出结果:

    true
    --------
    false
    false
    --------
    true
    true
    --------
    true
    true
    --------
    false
    true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.3 重写一下equals()

    调用这个方法

    
    class Person{
        int a;
        Person(int a){
            this.a = a;
        }
        public boolean equals(Person b){
            if(a == b.a){
                return  true;
            }
            return false;
        }
    }
    
    public class Test {
        
        public static void main(String[] args) {
            Person ap = new Person(1);
            Person bp = new Person(1);
            System.out.println(ap.equals(bp));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果:

    true
    
    • 1

    1.4 底层

    object类的equals()

    public boolean equals(Object obj) {
            return (this == obj);
        }
    
    • 1
    • 2
    • 3

    String类的equals()

    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2. HashSet

    HashSet是基于HashMap来实现的,实现了Set接口,同时还实现了序列化和可克隆化。
    其中最有趣的是hashcode()方法
    添加元素:

    import java.util.HashSet;
    
    public class Test {
        
        public static void main(String[] args) {
            HashSet<Integer> hash = new HashSet<>();
            hash.add(1);
            hash.add(2);
            System.out.println(hash);	// [1,2]
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    add()方法底层

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    
    • 1
    • 2
    • 3

    put()的底层

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    
    • 1
    • 2
    • 3

    hash()底层

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    
    • 1
    • 2
    • 3
    • 4

    hashCode就是对象的散列码,是根据对象的某些信息推导出的一个整数值,默认情况下表示是对象的存储地址。通过散列码,可以提高检索的效率,主要用于在散列存储结构中快速确定对象的存储地址,如Hashtable、hashMap中。


    Java的超类Object类已经定义了equals()和hashCode()方法,在Obeject类中,equals()比较的是两个对象的内存地址是否相等,而hashCode()返回的是对象的内存地址。所以hashCode主要是用于查找使用的,而equals()是用于比较两个对象是否相等的。但有时候我们根据特定的需求,可能要重写这两个方法,在重写这两个方法的时候,主要注意保持一下几个特性:
    (1)如果两个对象的equals()结果为true,那么这两个对象的hashCode一定相同;
    (2)两个对象的hashCode()结果相同,并不能代表两个对象的equals()一定为true,只能够说明这两个对象在一个散列存储结构中。
    (3)如果对象的equals()被重写,那么对象的hashCode()也要重写。


    假设我们我们重写了对象的equals(),但是不重写hashCode()方法,由于超类Object中的hashcode()方法始终返回的是一个对象的内存地址,而不同对象的这个内存地址永远是不相等的。这时候,即使我们重写了equals()方法,也不会有特定的效果的,因为不能确保两个equals()结果为true的两个对象会被散列在同一个存储区域,即 obj1.equals(obj2) 的结果为true,但是不能保证 obj1.hashCode() == obj2.hashCode() 表达式的结果也为true;这种情况,就会导致数据出现不唯一,因为如果连hashCode()都不相等的话,就不会调用equals方法进行比较了,所以重写equals()就没有意义了。

    3. 参考链接(看看)

    Java中哈希集(HashSet)概念,实现以及操作
    集合框架:Set集合的特点、HashSet集合的底层原理、哈希表、实现去重复
    必须掌握的hashcode()方法

    Java基础篇:什么是hashCode 以及 hashCode()与equals()的联系

  • 相关阅读:
    系统分析师难考吗?通过率大概是多少?
    解决flask重启后端口被占用的问题(非kill方法)
    【LeetCode-中等】221. 最大正方形(详解)
    12.LoadRunner,基于html录制和基于url录制
    trino tpcds测试
    MySQL数据库优化
    Spring Boot企业级开发教程课后习题——第2章Spring Boot核心配置与注解
    d隐式枚举猜
    PS端GPIO配置和基本介绍
    MediaPlayer使用以及常见问题
  • 原文地址:https://blog.csdn.net/weixin_51395608/article/details/138191488