微笑精灵 2021-07-17 21:28 采纳率: 94.1%
浏览 32
已采纳

为什么想要实现list实体转set实体去重,要重写hashcode和equals方法?

今天想要进行实体类集合,结果我list强制转型set报错了,然后我new HashSet<>(list);
这个虽然没报错,但是这个却没有实现去重。
有懂底层的能科普么?

  • 写回答

2条回答 默认 最新

  • 走一步-再走一步 2021-07-17 22:19
    关注

    HashSet的底层其实是封装了HashMap,而 new HashSet<>(list)
    底层就是调用了addAll 方法
    addAll 底层调用了add 方法,add 又调用了HashMap的 put(key,val) 方法
    HashMap 底层是数组+链表的结构
    其中如何判断map 中是否已经有值也就是所谓的去重 判断方法如下

    1. 计算 key 的hashCode值,在hashMap中找到 该key 存放在数组的位置的元素 p,然后判断
      元素p的hashCode值是否和需要添加的元素key 的hashCode值是否一致
      如果一致,再去判断 需要添加的key 和 p的key的 是否是同一个对象如果不是同一个对象,那么 调用equals 是否相等
      如果相等了,用新的值 替换掉旧的值

    判断是否相等的逻辑如下:

    p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k)))
    
    

    也就是说,重写了hashCode 和 equals 能实现去重,如果没有重写 equals ,只能 实现是同一个对象的去重,
    举个栗子
    class A{
    String name;
    public A(String name){
    this.name = name;
    }
    }

    不重写equals的话,
    A a = new A("wu");
    A b = new A("wu");

    在 HashMap中 哪怕 a和b的hashCode值相等
    但是 后续判断 a ==b 为false,因为a 和b的地址并不一样,
    a.equals(b) 也是false,因为没有重写 equals,那么该方法继承自 Object
    方法定义如下:

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

    其实还是判断地址是否一致

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已采纳回答 7月19日
  • 创建了问题 7月17日

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题