2011-04-18 60 views
4

我需要一個多線程的Map對象用於我的Web服務器的緩存,並且我需要有null鍵。線程安全的映射,具有空鍵功能

HashMap允許我具有空鍵,但ConcurrentHashMap沒有。我嘗試使用Collections.synchronizedMap(new HashMap())創建HashMap的同步版本,但它不接受null鍵。

是否有任何替代方案可以使用,而無需實施某種方式來包裝null鍵?

+1

HashMap只允許一個空鍵。你在談論空值嗎? – Pushkar 2011-04-18 07:33:35

+0

JDK 1.6.0_23,'Collections.synchronizedMap(new HashMap())'適用於'null'鍵和值。 – 2011-04-18 07:36:06

回答

6

Map返回的Collections.synchronizedMap支持您給它的Map的所有功能。如果你給它一個HashMap,它支持null密鑰(還有null值,你說「...我需要有」null「鍵值......」它可以讀取任何一種方式)。是什麼讓你覺得它不?

可正常工作,例如:

import java.util.*; 

public class MapTest 
{ 
    public static final void main(String[] args) 
    { 
     Map map; 

     try 
     { 
      map = Collections.synchronizedMap(new HashMap()); 
      map.put("one", "a"); 
      System.out.println("Size = " + map.size()); 
      map.put(null, "b"); 
      System.out.println("Size = " + map.size()); 
      System.out.println("map.get(null) = " + map.get(null)); 
     } 
     catch (Exception ex) 
     { 
      System.out.println("Exception: " + ex.getMessage()); 
      ex.printStackTrace(System.out); 
     } 
     System.exit(0); 
    } 
} 

輸出:

Size = 1 
Size = 2 
map.get(null) = b
+0

對,我的錯。我錯誤地爲我的測試使用了ConcurrentHashMap,而不是包裝的HashMap。謝謝。 – Iravanchi 2011-04-18 07:53:09

+0

@Iravanchi:LOL!容易做到。很高興幫助, – 2011-04-18 08:02:34

+0

這不太可能是服務器緩存的絕佳選擇。緩存將需要非常高的性能,即可以忽略的鎖定成本。 ConcurrentHashMap對此更好。如果你想允許null值,你可以通過擴展'ConcurrentHashMap'和重寫'put'方法來很容易地模擬它,當給定一個空值時執行'remove',之後該鍵的'get'將返回null,你仍然可以獲得更高的併發性能。 – rees 2012-10-27 04:22:23

2

據我知道有沒有一個簡單的方法,使ConcurrentHashMap,也不是一個等價類支持null鍵或值。

ConcurrentHashMapCollections.synchronizedMap(new HashMap())完全不同。

首先,因爲同步映射將阻止任何併發訪問同時發生,即使所有訪問都是隻讀的。 ConcurrentHashMap不會阻止併發讀取訪問,並且在某些情況下甚至可能接受併發寫入。

但更重要的是,如果在使用迭代器時修改了底層映射,則由同步映射返回的Iterator容易拋出ConcurrentModificationException。另一方面,即使在使用迭代器時更改底層映射,ConcurrentHashMap迭代器也保證永遠不會拋出ConcurrentModificationException