V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yurong3333333333
V2EX  ›  程序员

大家在什么业务场景使用对象作为 HashMap 的 key?

  •  
  •   yurong3333333333 · 2022-12-13 21:33:56 +08:00 · 2202 次点击
    这是一个创建于 471 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,求助大佬

    背景:搜索出一堆八股文在描述为什么要重写两个方法,但是没描述在什么样的业务场景中需要这么做,本人也没遇到过。

    第 1 条附言  ·  2022-12-13 22:07:08 +08:00
    考虑使用对象作为 key 的原因是什么?
    20 条回复    2022-12-16 14:05:08 +08:00
    t202201
        1
    t202201  
       2022-12-13 21:39:37 +08:00 via iPhone
    同问
    TWorldIsNButThis
        2
    TWorldIsNButThis  
       2022-12-13 21:40:14 +08:00
    很少,最多是几个基础类型的 Pair / Triple 或者在高版本里,用 record

    其实都帮你写好了 equals 和 hash code
    golangLover
        3
    golangLover  
       2022-12-13 21:43:20 +08:00
    没用过。。。。
    yesterdaysun
        4
    yesterdaysun  
       2022-12-13 21:56:02 +08:00   ❤️ 1
    有时会用在缓存的 key 上, 比如这个缓存需要一个一个 id 加另一个 id 才是唯一的, 之前可能会要字符串连接之类的, 换成对象就比较好, 不过只是纯感觉, 没有测过两者性能有多大差, 更多是为了类型安全和简单性可读性, 反正有 lombok 或者 record, equals 和 hashcode 都是自动的
    sunjiayao
        5
    sunjiayao  
       2022-12-13 21:58:53 +08:00
    最近用过的是把一个 SDK 的 Config 对象当做 Key
    orangie
        6
    orangie  
       2022-12-13 22:04:29 +08:00   ❤️ 1
    除了 Map ,还有 Set 这个集合也是需要使用 HashCode 的。Map 的 containsValue 方法应该也是要用到 hashCode 来快速比较的吧。
    orangie
        7
    orangie  
       2022-12-13 22:11:14 +08:00
    设想,如果一个 POJO 只重写了 equals ,没重写 hashCode ,那么两个对象可能因为内容是相同的所以 equals 是 true ,但是 openJDK 的默认 hashCode 实现是随机数(虽然 JDK 注释写的是内存地址),它们的 hashCode 应该是不同的,这种情况是荒谬的,不应该出现。
    5200721
        8
    5200721  
       2022-12-13 22:14:18 +08:00   ❤️ 1
    重写过一次,判断 Hive 库表的原信息和存储在 MySQL 中的 Hive 库表信息差异来更新 MySQL 中的数据。还踩了一个字符串对象为 null 和空串的坑。
    yurong3333333333
        9
    yurong3333333333  
    OP
       2022-12-13 22:39:36 +08:00
    @orangie 看清楚题目意思哈
    orangie
        10
    orangie  
       2022-12-13 22:48:45 +08:00
    如果一个对象有多个属性,而所有属性全部同时考虑在内才能判断唯一性,那么用对象本身(也就是它的 hashcode )作为 key 是唯一的选择,总不能为了有个字符串 key 把这个对象序列化吧?对应的数据库中表的情况就是所有字段形成了复合主键。但是好像很少会有这么设计的,倒是业务的中间过程有可能会出现这种情况。
    wolfie
        11
    wolfie  
       2022-12-13 23:14:53 +08:00
    pair 、tripple + 1
    组合 key
    dqzcwxb
        12
    dqzcwxb  
       2022-12-13 23:41:41 +08:00
    题外话,TreeMap 用的是 Comparable
    zhouhu
        13
    zhouhu  
       2022-12-14 00:17:25 +08:00
    hashCode 方法的返回(默认返回对象在内存中的地址)决定了对象在 HashMap 中的位置,equal (默认比较对象的内存地址)决定了两个对象是不是相等。要不要重写在于你的业务需求。
    tedzhou1221
        14
    tedzhou1221  
       2022-12-14 09:05:02 +08:00   ❤️ 1
    策略模式中,使用枚举类作为 HashMap 的 key
    theniupa
        15
    theniupa  
       2022-12-14 09:09:35 +08:00   ❤️ 1
    HashMap 用对象做 key 的场景还没碰到过。。
    只有用到过某些特定的场景需要多属性排序策略的时候 ,Comparable 对象做做 TreeMap 的 key ,比如 DirectByteBuffer 池
    lmshl
        16
    lmshl  
       2022-12-14 10:54:54 +08:00   ❤️ 1
    挺常见的吧,比如有些场景下我会用 java.time.LocalDate 做 key
    guyeu
        17
    guyeu  
       2022-12-14 18:45:17 +08:00
    鉴于 Java 不支持基本数据类型的泛型,所以没法不用对象当作 Map 的 key 。

    以下正经表达:重写 hashcode 和 equals 方法,刚才搜了以下你说的八股文,它们描述的是,为什么在用到哈希表的情况下需要重写这两个方法,这个就能回答你的第一个问题,需要重写这两个方法的业务场景是可能或已经用了哈希表的场景,包括但不仅限于 HashMap, HashSet, HashTable, ConcurrentHashMap...

    另外,用作 HashMap 的 key 的对象不拘泥于是什么类型,只要不是可变对象就不会出什么问题。业务中用的最多的是 String ,一些不讲究类型表达语义的编码里,经常会把其他的数据类型转成 String ,用作 HashMap 的 key ,在这些代码里,几乎就见不到其他类型作为 HashMap 的 key 。
    imv2er
        18
    imv2er  
       2022-12-14 20:57:36 +08:00
    举个例子
    人包含名字和钱。 给你一个 list 里面包含了很多人 ,又同一个人(名字相同),但是钱不同,你希望针对每一个人保留最后一条作为最终余额。
    你可以选择将他们放到 hashmap 去重。此时你重写人的 hashcode 和 equal 方法能保证结果
    aguesuka
        19
    aguesuka  
       2022-12-14 23:22:47 +08:00
    @tedzhou1221 你应该使用 EnumMap 而不是 HashMap
    zerofancy
        20
    zerofancy  
       2022-12-16 14:05:08 +08:00 via Android
    安卓开发,activity 作为 WeakHashMap 的 key ,因为 key 是 weak 的,存储 activity 集合不发生内存泄漏
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5847 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:58 · PVG 09:58 · LAX 18:58 · JFK 21:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.