String IdentityHashMap vs HashMap性能

Him*_*ire 5 java collections hashtable hashmap

Identity HashMap是java中的特殊实现,它比较对象引用而不是equals,并且还使用identityHashCode而不是hashCode.另外它用来linear-probe hash table代替Entry list.

Map<String,String> map = new HashMap<String,String>(); 

Map<String,String> iMap = new IdentityHashMap<String,String>();
Run Code Online (Sandbox Code Playgroud)

这是否意味着对于String键,如果正确调整,IdentifyHashMap通常会更快?

添加了一些基本代码

public class Dictionary {

public static void main(String[] args) throws IOException {

    BufferedReader br = new BufferedReader(new FileReader("/usr/share/dict/words"));

    String line;
    ArrayList<String> list = new ArrayList<String>();


    int index=0;
    while( (line = br.readLine()) != null){
        list.add(line);
    }
    System.out.println("list.size() = " + list.size());
    Map<String,Integer> iMap = new IdentityHashMap<String,Integer>(list.size());
    Map<String,Integer> hashMap = new HashMap<>(list.size());

    long iMapTime=0,hashMapTime=0;

    long time=0;
    for(int i=0; i< list.size(); i++){
        time= System.currentTimeMillis();
        iMap.put(list.get(i),i);
        time = System.currentTimeMillis()-time;
        iMapTime += time;
        time= System.currentTimeMillis();
        hashMap.put(list.get(i),i);
        time = System.currentTimeMillis()-time;
        hashMapTime += time;
    }

    System.out.println("iMapTime = " + iMapTime + " hashMapTime = " +hashMapTime);

}
Run Code Online (Sandbox Code Playgroud)

}

尝试了非常基本的性能检查.我正在阅读字典单词(235K)并推入两张地图.它打印在下面.

list.size() = 235886
iMapTime = 101 hashMapTime = 617 
Run Code Online (Sandbox Code Playgroud)

我认为这是非常好的改进,除非我在这里做错了.

biz*_*lop 4

怎样IdentityHashMap<String,?>运作?

要使IdentityHashMap<String,?>任意字符串工作,您必须同时使用您传递给String.intern()的键和潜在的键。(或使用等效机制。)put()get()

注意:与 @m3th0dman 的答案中所述不同,您不需要intern()这些值。

无论哪种方式,驻留字符串最终都需要在某种已驻留字符串的哈希表中查找它。因此,除非您出于其他原因必须实习您的字符串(因此已经支付了成本),否则您不会从中获得太多实际的性能提升。

那么为什么测试表明你可以呢?

您的测试不切实际的地方是您保留了所使用的键的确切列表put(),并按列表顺序一一迭代它们。注意(通过将元素插入 aLinkedHashMap并简单地调用iterator()其条目集可以实现相同的效果。

那还有什么意义呢IdentityHashMap

在某些情况下,可以保证(或实际上保证)对象标识与 相同equals()。例如,想象一下尝试实现您自己的ThreadLocal类,您可能会编写如下内容:

public final class ThreadLocal<T> {
   private final IdentityHashMap<Thread,T> valueMap;
   ...
   public T get() {
       return valueMap.get( Thread.currentThread() );
   }
}
Run Code Online (Sandbox Code Playgroud)

因为您知道线程除了身份之外没有平等的概念。如果您的映射键是枚举值等,情况也是如此。