Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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_Concurrenthashmap - Fatal编程技术网

Java 保证密钥唯一时HashMap的性能

Java 保证密钥唯一时HashMap的性能,java,performance,hashmap,concurrenthashmap,Java,Performance,Hashmap,Concurrenthashmap,如果我希望使用的键保证是唯一的(或者至少可以假设键是唯一的),那么使用“香草”是否提供了最佳性能,或者是否需要修改哈希函数或put方法以避免不必要的哈希 此外,数字键是否比非数字键(例如具有适当哈希函数的字符串或POJO)有任何性能优势?如评论中所述,如果不需要线程安全特性,则不要使用ConcurrentHashMap 如果你想要绝对的最佳性能,请考虑使用键。这避免了计算对象的散列(并且,如注释中所述,不需要计算等于),而是假设引用本身就是散列 请注意,显然您必须确保同一个键的两个实例是同一个对

如果我希望使用的键保证是唯一的(或者至少可以假设键是唯一的),那么使用“香草”是否提供了最佳性能,或者是否需要修改哈希函数或put方法以避免不必要的哈希


此外,数字键是否比非数字键(例如具有适当哈希函数的字符串或POJO)有任何性能优势?

如评论中所述,如果不需要线程安全特性,则不要使用
ConcurrentHashMap

如果你想要绝对的最佳性能,请考虑使用键。这避免了计算对象的散列(并且,如注释中所述,不需要计算

等于
),而是假设引用本身就是散列

请注意,显然您必须确保同一个键的两个实例是同一个对象(例如,您必须确保引用相等,而不仅仅是对象相等)。实习你所有的钥匙是实现这一点的方法之一

实现说明:这是一个简单的线性探测哈希表,如Sedgewick和Knuth在文本中所述。数组交替保存键和值。(对于大型表,这比使用单独的数组具有更好的局部性。)对于许多JRE实现和操作混合,此类将产生比HashMap(使用链接而不是线性探测)更好的性能


如果你知道所有的钥匙,也许你也可以考虑一下。或者映射到一个简单的数组结构?

ConcurrentHashMap是最昂贵的HashMap实现,因为它是线程安全的

所有地图都必须有唯一的键,因此这是一个给定的

如果您使用支持诸如TLongHashMap之类的原语的集合,则使用数字具有性能优势,但是使用自定义HashMap可能会更快


Java的HashMaps最终由
Entry
数组支持,其中K的hashcode用于确定数组中存储该项的插槽

所用数组的大小(通常从16开始)远小于可能的哈希代码数(2^32~=40亿),因此,即使哈希代码是唯一的,该数组中也必然存在冲突

只要hashcode()方法是快速的,用作键的类型之间就没有区别。请记住,hashcode()方法可能会被多次调用,因此如果调用速度较慢,可以在对象内部缓存它

如果我希望使用的密钥保证是唯一的(或者至少可以假设密钥是唯一的),那么使用“香草”ConcurrentHashMap是否提供最佳性能

如果
Map
是一个潜在的并发瓶颈,您通常会使用
ConcurrentHashMap
。如果应用程序是单线程的,或者没有争用,
ConcurrentHashMap
HashMap

或者是否需要修改哈希函数或put方法以避免不必要的哈希

哈希函数在哈希表的每个“探测”中计算一次;e、 g.每次
get
put
操作一次。您可以通过缓存结果来降低哈希函数的成本,但这会为每个密钥对象额外花费4字节的存储空间。缓存是否值得优化取决于:

  • 与应用程序的其余部分相比,散列的相对成本是多少,以及
  • 实际使用缓存值的对
    hashCode()
    的调用比例
这两个因素都具有高度的应用特定性

(顺便提一下,使用标识哈希代码作为哈希值的长期成本也是额外的4字节存储。)

此外,数字键是否比非数字键(例如具有适当哈希函数的字符串或POJO)具有任何性能优势


在数字情况下,哈希函数可能更便宜,但它是否值得,取决于使用数字键是否存在特定于应用程序的缺点。如上所述,相对成本是应用程序特定的。例如,
String.hashCode()
的成本与被散列的字符串的长度成正比。

我有ConcurrentHashMap实例映射,可通过多线程访问。请参见下面的代码片段。这些怎么样

Iterator<String> it = new TreeSet<String>(map.keySet()).iterator();
            while(it.hasNext())
            {
                id = it.next();
                synchronized(map)
                {
                    msg = map.get(id);
                    if(msg != null)
                        map.remove(id);
                }
                if(msg != null)
                listener.procMessage(msg);
            }
Iterator it=newtreeset(map.keySet()).Iterator();
while(it.hasNext())
{
id=it.next();
同步(地图)
{
msg=map.get(id);
如果(msg!=null)
地图删除(id);
}
如果(msg!=null)
procMessage(msg);
}

如果您不需要线程安全特性,请不要使用ConcurrentHashMap,使用HashMapIt也不要使用equals()方法。要进行查找,您必须使用完全相同的对象。@Peter,说得好,更新了答案以反映您的评论。“nonimal”表示两分钟内小于0.1MB。i、 e.比我认为值得测量的少。在这个测试中,地图几乎立即达到一个特定的大小,之后就不再增长了。@Peter Lawrey我想你的意思是“换句话说。。。没有非动物这样的动物:-)
Iterator<String> it = new TreeSet<String>(map.keySet()).iterator();
            while(it.hasNext())
            {
                id = it.next();
                synchronized(map)
                {
                    msg = map.get(id);
                    if(msg != null)
                        map.remove(id);
                }
                if(msg != null)
                listener.procMessage(msg);
            }