【问题标题】:Will similar Strings in HashMap lead to increased chance of collisions?HashMap 中的类似字符串会导致碰撞几率增加吗?
【发布时间】:2017-05-17 17:41:33
【问题描述】:

考虑以下几点:

HashMap<String, Object> hm = new HashMap<>();
final String prefix = "My objects ";
int counter = 0;

void put(Object value) {
    hm.put(prefix+(counter++), value);
}

鉴于每个条目的键都以相同的字符串开头并且仅附加一个数字不同,这是否可能导致更多的冲突?从性能的角度来看,我正在尝试确定这种创建唯一键的方式是否是一个好主意。

【问题讨论】:

  • 为什么不直接使用整数键?
  • 通用前缀不会有坏处,但将整数转换为字符串...可能。
  • @Eran 公平点,但这只是一个小例子,出于其他原因,我需要将密钥作为字符串。

标签: java hashmap hash-collision string-hashing


【解决方案1】:

不,它不会。因为String#hashcode,这不是必要;但是因为 HashMap 将通过对前 16 位与最后 16 位进行异或运算来重新散列您的哈希码。

// this is re-hashing that is done internally
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

但即使那增加碰撞,你也可能永远感觉不到。 对于条目一个接一个(以链接方式)放置的小桶/bin,将调用equals 以获取您关心的实际条目。

如果某个 bin/bucket 达到某个阈值,它将转换为 perfectly balanced tree node。在这样一棵树中的搜索时间是0(logn)

即使如果相同的条目在重新散列之后报告相同的哈希码,映射仍然要决定哪个条目在更大中平局的情况。

然后它会尝试调用Comparable#compareTo,以防您的键实现 Comparable。如果他们没有实现ComparableSystem.identityHashcode 将被调用来决定是否出现平局。

正如您从性能角度所说,由于所有这些内部因素,您的平均搜索时间将是地图中的O(1)

【讨论】:

  • 非常全面的答案。谢谢!
猜你喜欢
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 2011-03-28
  • 2021-12-31
相关资源
最近更新 更多