zoukankan      html  css  js  c++  java
  • Equals()和HashCode()方法的密切关系

    一、equals方法是判断俩个对象是否相等的唯一依据

        public boolean equals(Object obj) {
            return (this == obj);
        }

    equals方法是Object类定义的方法,在Object中equal方法比较的内存地址,无法判断对象的具体内容是否一样。要对内容准确的判断必须重写equals方法,如java中String、Integer、Double等包装类都做了equals方法的重写。

    String类:

        public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                char val[] = value;
    
                for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
                hash = h;
            }
            return h;
        }

    Integer:(数字本身就唯一,惊不惊喜)

        public static int hashCode(int value) {
            return value;
        }

    二、为什么要用到hashCode方法

    我们知道在重写equals方法后,必须重写hashCode方法。

    并且要保证:

    1、equals方法为true的两个对象,hashCode方法的返回值必须相同。

    2、并不要求两个不同对象的hashCode值一定不同。

    那么之所以要用到hashCode方法,是为了查询效率。

    例如:HashSet这个集合,它的元素,必须是唯一的。要保证它的唯一,用equals是可以实现的,但是如果元素较多,假如有一万个元素,那么就要调用一万次equals方法进行比较,才能确定要不要添加这个元素。同样,查询也一样,要比较一万次,才能确定集合里有没有这个元素。

    那么,现在使用HashCode方法,可以形象的理解,每一个元素的hashcode值就是它在集合中的位置。

    在插入的时候,因为保证了equeal相同的对象,hashcode值一定相同,所以

    1、首先看看该HashCode值对应的集合位置有没有元素存在。

    2、如果不存在,说明集合没有该元素,插入;如果存在,在调用equals方法进行比较。值为true,不插入;值为false,插入(怎么插入相同位置?可以在相同HashCode值位置维护一个链表,毕竟不同元素HashCode值可能相同)。

    同样,在查询的时候,也是

    1、先查询该元素的hashCode

    2、再去hashCode值对应的集合位置依次比较链表的各个元素。

    这个查询效率是不是显著增加。这其实就是Hash算法,一个叫hash的人首先发现的。

    所以在使用一个HashSet存储自定义实体类时,一定要重写Equals和hashCode方法,否则HashSet并不会起到无序的作用。

    总结:equals是比较两个对象内容是否相同的唯一依据,hashCode值只是帮助集合快速找到该对象可能存在的位置。

    其实,HashSet的实现,是保存在HashMap的key中。

        public HashSet() {
            map = new HashMap<>();
        }
    
        public Iterator<E> iterator() {
            return map.keySet().iterator();
        }
    
        public int size() {
            return map.size();
        }

    以上的HashSet方法可以明显看书,HashSet其实就是借用了HashMap的Key。

    三、一个简单实体类重写Equals和HashCode(IntelliJ自动生成)

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.HashSet;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class CustomData {
        private String name;
        private Integer age;
    
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            if (!super.equals(o)) return false;
    
            CustomData that = (CustomData) o;
    
            if (!name.equals(that.name)) return false;
            return age.equals(that.age);
        }
    
        @Override
        public int hashCode() {
            int result = super.hashCode();
            result = 31 * result + name.hashCode();
            result = 31 * result + age.hashCode();
            return result;
        }
    }
    就算这个世道烂成一堆粪坑,那也不是你吃屎的理由
  • 相关阅读:
    ssm利用ajax上传图片和参数
    ssm+rabbitmq 分布式实例
    ssh免密
    springboot中aop的尝试
    springboot中自定义属性实体类和应用
    滑动门--------实现导航栏背景图自适应文字内容多少
    嵌套块元素垂直外边距的合并(塌陷)
    vue项目处理时间戳问题
    vue项目中遇到的登录超时
    标签显示模式
  • 原文地址:https://www.cnblogs.com/whalesea/p/12934644.html
Copyright © 2011-2022 走看看