Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HashMap的字符串键的长度被认为是错误的做法?_Java_Performance_Hashmap - Fatal编程技术网

Java HashMap的字符串键的长度被认为是错误的做法?

Java HashMap的字符串键的长度被认为是错误的做法?,java,performance,hashmap,Java,Performance,Hashmap,我一直努力关注良好的性能和干净的代码 我很难理解一个具有150个字符的键的HashMap是否合理 HashMap键的长度是否有不成文的规则 使用150个字符的字符串键被认为是不好的做法吗 它会影响性能吗?多长时间 HashMap键的长度是否有不成文的规则 如果有的话,也是没有说出来的。我会在剖析器中度量您的用例,只担心您可以度量为问题的东西,而不是您可以想象可能成为问题的东西 使用150个字符的字符串键被认为是不好的做法吗 我对此表示怀疑 它会影响性能吗?多长时间 任何事情都会影响性能,通常

我一直努力关注良好的性能和干净的代码

我很难理解一个具有150个字符的键的HashMap是否合理

  • HashMap键的长度是否有不成文的规则
  • 使用150个字符的字符串键被认为是不好的做法吗
  • 它会影响性能吗?多长时间
HashMap键的长度是否有不成文的规则

如果有的话,也是没有说出来的。我会在剖析器中度量您的用例,只担心您可以度量为问题的东西,而不是您可以想象可能成为问题的东西

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

我对此表示怀疑

它会影响性能吗?多长时间

任何事情都会影响性能,通常是小到重要,有时甚至可以衡量。问题应该是,;你需要150个字符的密钥吗。如果你这样做了,那么就使用它们


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


不太可能,150个字符的字符串对于计算一个
hashCode
来说是相对简单的

也就是说,在这种情况下,我建议你测试一下

创建一个例程来填充HashMap,例如,在此处插入一个大小,该大小代表使用5个字符串作为键的使用场景随机值。测量需要多长时间。然后对15个字符的关键点执行相同的操作,并查看其缩放效果

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


这意味着,尽管您在创建映射时正在计算更大的哈希代码,但在访问时,许多哈希代码已经被预先计算和缓存,使得原始字符串的大小更加不相关。

详细回答:快速查看
字符串::哈希代码()的源代码
显示哈希在第一次调用后被缓存。同时,如果字符串相等但不相同,
String::equals()
为O(n)(即,
equals()
为true,但
==
为false,因为它们分配在不同的地址)

因此,您将看到以下方面对性能的影响:

  • 在调用
    HashMap
    函数时,在散列字符串之前传递never。但是,生成大量新字符串本身会影响性能

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

  • 此外,字符串文本、字符串常量和手动
    intern()
    'd字符串加入字符串常量池,其中所有“相等”字符串都是具有相同地址的相同对象。因此,如果只处理这样的字符串,
    hashCode
    equals
    非常快

当然,除非在紧循环中执行上述操作(因为150个字符并不长,hashCode()和equals()都很有效),否则性能影响根本不会明显

简短回答:基准。

首先,没有“不成文规则”。如果从算法角度看,长字符串作为键是有意义的,那么就使用它们。如果分析表明存在问题,则需要进行优化

那么长字符串如何影响哈希表的性能呢

  • 长字符串比短字符串占用更多的内存,这可能会导致更长的垃圾收集时间,以及与硬件内存缓存、TLB和(可能)物理内存页争用相关的其他次要性能影响

  • 字符串的hashcode算法使用字符串的所有字符,因此其成本与字符串长度成正比。缓存字符串哈希代码的事实缓解了这一问题。(第二次和以后对字符串调用
    hashcode
    时,您将获得缓存的值。)但是,这只有在使用同一字符串对象作为键执行多个哈希表操作时才有帮助

  • 当出现哈希冲突时,哈希表会返回到使用
    String.equals()
    在搜索所选哈希链时比较键。在最坏的情况下(例如,当字符串
    相等而不是
    =
    )时,
    String.equals()
    涉及比较两个字符串的所有字符


如您所见,这些影响将特定于实际应用程序,因此很难预测。因此,“不成文的规则”不太可能有帮助。

这里吹毛求疵,但java每个字符使用的字节远远超过1个。@radai True,即使使用
-XX:+UseCompressedStrings
每个字符可以使用一个字节。另一个吹毛求疵:java 7的
HashMap
修复了它,而不是
String
String#hashCode
基本没有变化。我的观点是:除了
HashMap
和其他Java集合框架类之外,整个机制是不可访问的。无论您自己的逻辑依赖于
对象#hashCode
,您都无法从中获益