在哪个长度是HashMap的String键被认为是不好的做法?

Car*_*ine 17 java performance hashmap

我一直在努力关注良好的性能和清洁代码.

我很难掌握使用带有150个字符的键的HashMap是否合理.

  • HashMap密钥的长度是否有不成文的法律?
  • 让字符串键为150个字符被认为是不好的做法吗?
  • 它会影响性能吗?在哪个长度?

pca*_*cao 14

不是真的,150个字符串字符串计算hashCodefor 是相对微不足道的.

话虽这么说,在这样的情况下,我建议你测试一下!

创建一个填充HashMap的例程,例如,在这里插入一个代表您的使用场景随机值的大小,其中5个字符串作为键.测量需要多长时间.然后对15个字符键执行相同操作,并查看它是如何缩放的.

此外,Java中的字符串是不可变的,这意味着hashCode可以为存储在字符串常量池中的每个字符串缓存,并且在同一String对象上调用hashCode时不需要重新计算.

这意味着虽然您在创建地图时计算较大的哈希码,但在访问时,许多哈希码已经预先计算和缓存,使得原始字符串的大小更不相关.


Pet*_*rey 9

HashMap密钥的长度是否有不成文的法律?

如果有,它也是未说出口的.我会在分析器中测量你的用例,只担心你可以测量的问题,而不是你能想象的可能是一个问题.

让字符串键为150个字符被认为是不好的做法吗?

我对此表示怀疑.

它会影响性能吗?在哪个长度?

一切都会影响性能,通常是小到重要或有时甚至是衡量.问题应该是; 你需要150个字符键吗?如果你这样做,那就用它们吧.


有一种奇特的情况,添加hashCode()为零的字符串是一个坏主意.这是因为在Java 1.0到6中没有优化hashCode为零的用例,并且可以预测拒绝服务攻击.Java 7通过使用次要的,不太可预测的哈希码来解决这个问题.

为什么String的hashCode()没有缓存0?

  • 我的观点:整个机制在`HashMap`和其他Java Collection Framework类之外是不可访问的.无论你有什么逻辑依赖于'Object#hashCode`,你都无法从增强中获益.这是值得注意的. (2认同)
  • Java 8通过删除`hash32`来解除它.由于在许多冲突的情况下使用树容器,这是可以的. (2认同)

Ale*_*sky 5

答案很简单:快速查看源代码,可以String::hashCode()看出哈希在第一次调用后被缓存了.同时,String::equals()如果字符串相等但不相同(即,equals()为真,但==因为它们在不同的地址分配),则为O(n ).

因此,您将看到对性能的影响:

  • 在调用HashMap函数时传递前所未有的字符串.但是,生成大量新字符串本身会影响性能.

  • 调用HashMap::get()HashMap::put()使用等于HashMap中已有的键的字符串键(因为如果键不在集合中,那么很可能只调用hashCode().但如果是,则equals()将进行比较所有字符,直到它确定字符串是相等的).但是,只有传递给这些函数的字符串与HashMap中已经存在的字符串不同,因为在这种情况下equals()非常快.

  • 此外,字符串文字,字符串常量和手动intern()'d字符串连接字符串常量池,其中所有"相等"字符串是具有相同地址的同一对象.因此,如果只使用这样的字符串,hashCode并且equals非常快.

当然,除非您在紧密循环中执行上述操作(因为150个字符不长并且hashCode()和equals()都有效),否则性能影响根本不会引人注意.

简短回答:基准.