Java HashMap的字符串键的长度被认为是错误的做法?
我一直努力关注良好的性能和干净的代码 我很难理解一个具有150个字符的键的HashMap是否合理Java HashMap的字符串键的长度被认为是错误的做法?,java,performance,hashmap,Java,Performance,Hashmap,我一直努力关注良好的性能和干净的代码 我很难理解一个具有150个字符的键的HashMap是否合理 HashMap键的长度是否有不成文的规则 使用150个字符的字符串键被认为是不好的做法吗 它会影响性能吗?多长时间 HashMap键的长度是否有不成文的规则 如果有的话,也是没有说出来的。我会在剖析器中度量您的用例,只担心您可以度量为问题的东西,而不是您可以想象可能成为问题的东西 使用150个字符的字符串键被认为是不好的做法吗 我对此表示怀疑 它会影响性能吗?多长时间 任何事情都会影响性能,通常
- HashMap键的长度是否有不成文的规则
- 使用150个字符的字符串键被认为是不好的做法吗
- 它会影响性能吗?多长时间
有一种奇特的情况,添加hashCode()为零的字符串是个坏主意。这是因为Java 1.0到6中没有优化哈希代码为零的用例,可以预测它是否会遭到拒绝服务攻击。Java7通过使用次要的、不太可预测的哈希代码来解决这个问题
不太可能,150个字符的字符串对于计算一个
hashCode
来说是相对简单的
也就是说,在这种情况下,我建议你测试一下
创建一个例程来填充HashMap,例如,在此处插入一个大小,该大小代表使用5个字符串作为键的使用场景随机值。测量需要多长时间。然后对15个字符的关键点执行相同的操作,并查看其缩放效果
此外,Java中的字符串是不可变的,这意味着可以为存储在字符串常量池中的每个字符串缓存hashCode
,并且在对同一字符串对象调用hashCode时不需要重新计算
这意味着,尽管您在创建映射时正在计算更大的哈希代码,但在访问时,许多哈希代码已经被预先计算和缓存,使得原始字符串的大小更加不相关。详细回答:快速查看
字符串::哈希代码()的源代码
显示哈希在第一次调用后被缓存。同时,如果字符串相等但不相同,String::equals()
为O(n)(即,equals()
为true,但==
为false,因为它们分配在不同的地址)
因此,您将看到以下方面对性能的影响:
- 在调用
函数时,在散列字符串之前传递never。但是,生成大量新字符串本身会影响性能HashMap
- 使用与HashMap中已存在的键相等的字符串键调用
和HashMap::get()
(因为如果该键不在集合中,则很可能只调用hashCode()。如果是,equals()将比较所有字符,直到确定字符串相等为止)。但仅当传递给这些函数的字符串不是HashMap中已经存在的相同对象时,因为在这种情况下,HashMap::put()
非常快equals()
- 此外,字符串文本、字符串常量和手动
'd字符串加入字符串常量池,其中所有“相等”字符串都是具有相同地址的相同对象。因此,如果只处理这样的字符串,intern()
和hashCode
非常快equals
- 长字符串比短字符串占用更多的内存,这可能会导致更长的垃圾收集时间,以及与硬件内存缓存、TLB和(可能)物理内存页争用相关的其他次要性能影响
- 字符串的hashcode算法使用字符串的所有字符,因此其成本与字符串长度成正比。缓存字符串哈希代码的事实缓解了这一问题。(第二次和以后对字符串调用
时,您将获得缓存的值。)但是,这只有在使用同一字符串对象作为键执行多个哈希表操作时才有帮助hashcode
- 当出现哈希冲突时,哈希表会返回到使用
在搜索所选哈希链时比较键。在最坏的情况下(例如,当字符串String.equals()
相等而不是
)时,=
涉及比较两个字符串的所有字符String.equals()
如您所见,这些影响将特定于实际应用程序,因此很难预测。因此,“不成文的规则”不太可能有帮助。这里吹毛求疵,但java每个字符使用的字节远远超过1个。@radai True,即使使用
-XX:+UseCompressedStrings
每个字符可以使用一个字节。另一个吹毛求疵:java 7的HashMap
修复了它,而不是String
String#hashCode
基本没有变化。我的观点是:除了HashMap
和其他Java集合框架类之外,整个机制是不可访问的。无论您自己的逻辑依赖于对象#hashCode
,您都无法从中获益