【问题标题】:Java HashSet remove item by using its hash code [closed]Java HashSet 使用其哈希码删除项目 [关闭]
【发布时间】:2021-05-19 05:44:11
【问题描述】:

我有一个类有自己的 hashCode() 方法。我正在将此类添加到 HashSet。如何在不知道对象本身的情况下通过其 hashCode 删除项目?

例如,如果我有以下代码

HashSet<Data> set = new HashSet<>();
set.add(new Data(10, 5));
...
class Data {
    public int importantVal;
    public int notImportantVal;
    //... constructor ...
    @Override
    public int hashCode() {
        return importantVal;
    }
}

我知道 Data 对象的importantVal,但不知道对象本身。我将如何删除它? set.remove(10) 不起作用。

我能想到的最佳解决方案是如果importantVal 相同,也覆盖equals() 以返回,然后执行set.remove(new Data(10, anyPlaceholderValue))

我正在寻找 O(1) 的解决方案。我显然知道如何遍历 HashSet 并检查每个元素,但这太慢了。

【问题讨论】:

  • 您确实意识到哈希码可能不是唯一的,对吧?一个集合中可能有多个不相等的对象,它们都具有相同的哈希码。在这种情况下,您要删除所有这些吗?
  • “我能想到的最佳解决方案是,如果 importantVal 相同,则也覆盖 equals() 以返回”。那么equals不是现在就这样实现了吗?那么equals是如何实现的呢?
  • 我认为如果 importantVal 对所有对象都是唯一的,那么 set.remove(new Data(10, anyPlaceholderValue)) 将给出 O(1) 复杂性。但前提是equals方法定义正确。
  • 听起来你应该使用 Map&lt;Integer, Data&gt; 而不是 set。
  • 你的 hashCode 和 equals 方法应该绝对遵循相同的逻辑?!

标签: java hash set hashset hashcode


【解决方案1】:

不,需要对象,哈希码不够

如何在不知道对象本身的情况下通过其 hashCode 删除项目?

你不能。

哈希码只是在HashSetHashMap 中跟踪对象的第一步。

哈希码不一定是唯一的。两个不同的对象可能巧合地具有相同的哈希码结果。此类碰撞是意料之中的。

因此构建了一个基于散列的集合,以将碰撞对象作为一个组进行二次跟踪,并使用equals 方法处理它们。相等用于区分碰巧产生相同哈希码计算结果的对象。

因此,您不能仅使用哈希码计算值从哈希驱动的集合中检索对象。相等性测试需要原始对象。

这就解释了为什么你的equalshashCode 方法必须使用相互一致的逻辑。当然,永远不要在不覆盖另一个的情况下覆盖其中一个。

请参阅:How does a Java HashMap handle different objects with the same hash code?

Map

如果您想通过该类的特定属性(例如唯一标识符)来跟踪对象以便快速检索,请使用Map 而不是Set。地图跟踪键值对。

例如,我们希望通过分配给每个人的标识符 UUID 来跟踪每个人。

record Person ( UUID id , String name , String phone ) {}

所以我们定义了一个 UUID 到 Person 的映射。

Map< UUID , Person > map = new HashMap<>() ;

实例化该类的一个对象。

UUID id = UUID.fromString( "5595d84e-b86b-11eb-8529-0242ac130003" ) ;
Person alice = new Person( id , "Alice" , "555-1234" ) ;

Person 对象添加到地图。

map.put( alice.id() , alice ) ;

检索。

Person x = map.get( UUID.fromString( "5595d84e-b86b-11eb-8529-0242ac130003" ) ) ;

【讨论】:

  • “奥莱铁”?西班牙合金?
  • @tgdavies 我将不得不解雇 Siri 作为我的文案编辑器。谢谢,现在修好了。
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-03
  • 2013-12-21
  • 1970-01-01
  • 2021-06-01
相关资源
最近更新 更多