【问题标题】:Custom key generation and collision in a hashMaphashMap 中的自定义键生成和冲突
【发布时间】:2021-08-13 19:05:16
【问题描述】:

我有一个方法可以将一个对象保存在一个以String为键的哈希映射(用作缓存)中。
在方法中传递的对象要么具有“易失性”字段,即它们可以在数据存储的下一次刷新时更改,要么在所有对象中都相同,除了 3 个字段。
这些字段是double 类型的2 个字段和String 类型的1 个字段。
我现在正在做的是我使用:

Objects.hash(doubleField1, doubleField2, theString)   

并将结果转换为String

基本上我是根据不可变状态为该对象生成一个密钥。

这似乎可行,但我有以下问题:

如果我们排除我们有 2 个具有完全相同字段的对象的情况(这是不可能的),我最终会发生无法正确验证的冲突的可能性有多大?
我的意思是,如果我有一个带有键的哈希图,例如字符串等如果在 hashCode 上发生冲突,则比较键的实际值以验证它是否是同一个对象而不是冲突。
以我描述的方式使用密钥会在此类验证中产生问题吗?

更新:
如果我有例如使用fullNamessndateOfBirth 生成键为PersonhashCode 的hashmap 如果存在冲突,则hashmap 实现使用equals 来验证它是否是正在搜索的实际对象为。
我想知道我描述的方法是否可能在该部分存在一些问题,因为我直接生成了实际密钥

【问题讨论】:

  • 如果您在谈论 hashCode 更改的键,那么这是一个坏主意。键应该是不可变的。如果您在谈论碰撞,那么我认为这应该不是问题。 hashCode 实现可以返回一个像 42 这样的常量。但是这样您的映射将不会非常有效,因为它会退化为一个链表。但我不完全确定您所说的验证是什么意思。
  • HashMap(以及HashSet)不仅通过hashcode()识别对象,还通过equals()识别对象,因此满足Hashcode/Equals contract很重要。
  • @WJS: 1) 密钥不会改变。 2)如果我有,例如使用fullNamessndateOfBirth 生成键为PersonhashCode 的hashmap 如果存在冲突,则hashmap 实现使用equals 来验证它是否是正在搜索的实际对象为了。我想知道我描述的方法在那部分是否有问题
  • 如果您在HashMap 中使用哈希作为键并且发生冲突,则使用相同键存储在HashMap 中的第一个对象将丢失。
  • 是的。这是一种选择。

标签: java hash hashmap collision-detection hash-collision


【解决方案1】:

这里是 hashMap 键实现的简单演示。在检索对象时,我会零碎地构造字段以避免使用缓存的字符串或整数的任何可能性。它使演示更具说服力。

Map<MyKey, Long> map = new HashMap<>();
map.put(new MyKey(10,"abc"), 1234556L);
map.put(new MyKey(400,"aefbc"), 548282L);

int n = 380;
long v = map.get(new MyKey(n + 20, "ae" + "fbc")); // Should get 548282
System.out.println(v);

打印

548282

关键类

class MyKey {
    privat eint v;
    private String s;
    private int hashcode;
    
    public MyKey(int v, String s) {
        Objects.requireNonNull(s, "String must be provided");
        this.v = v;
        this.s = s;
        // this class is immutable so no need to keep 
        // computing hashCode
        hashcode = Objects.hash(s,v);
    }
    @Override
    public int hashCode() {
        return hashcode;
    }
    
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o == null) {
            return false;
        }
        if (o instanceof MyKey) {
            MyKey mk = (MyKey)o;
            return v == mk.v && s.equals(mk.s);
        }
        return false;
    }
}

【讨论】:

    猜你喜欢
    • 2017-09-14
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多