2013-05-30 30 views
1

我有一個遺留應用程序,他們使用ConcurrentHashMap。現在我們已經知道concurrentHasMap是無序的,但是讀取對象的原始插入是必需的。我的代碼已經存在了一段時間的生產,因此我正在尋找快速替代品來替換集合,這也可以讓我訂購。基本上尋找一種非侵入性解決方案,可以最小化代碼更改。我搜索了Web並獲得了ConcurrentSkipListMap作爲替代方案,但它不適用於我。原因是,默認情況下,它按照密鑰的自然順序進行排序,這對我不起作用。由於我的密鑰是字符串,我需要基於插入命令而不是在地圖中自然排序字符串密鑰。有序(自然插入順序)和線程安全Java地圖

請儘早提出一些替代方案。

感謝 Anubhav

+0

_it對key_的自然排序命令稱爲'sorted'。也許你應該使用'LinkedHashMap(concurrentlinkedhashmap)'。 – Sam

+1

下面是一個ConcurrentLinkedHashMap:https://code.google.com/p/concurrentlinkedhashmap/ – maba

回答

0

您應該能夠使用LinkedHashMap保留插入順序,並使用Collections.synchronizedMap(Map map)方法使得​​。

public class Test { 
    Map<String, String> map = new LinkedHashMap<>(); 
    Map<String, String> test = Collections.synchronizedMap(map); 

    public void test() { 
    test.put("Z", "Zed"); 
    test.put("A", "Ay"); 
    for (String s : test.keySet()) { 
     System.out.println(s); 
    } 
    } 

    public static void main(String args[]) { 
    try { 
     new Test().test(); 
    } catch (Throwable t) { 
     t.printStackTrace(System.err); 
    } 
    } 

} 

此打印:

Z 
A 

根據您的需要。

+0

這是一個重要的改變 - 迭代需要同步,並且CHM特定的方法(如putIfAbsent)不會輕易替換。 – assylias

+0

@assylias - 同意 - 這隻有在OP不使用這些方法時纔有效。 – OldCurmudgeon

0

您可以自己重新排序密鑰。像這樣的東西可能是可能的。請注意,這不是一個完整的解決方案,需要做很多額外的工作才能正確實施ConcurrentMap

class InsertOrderedMap<K, V> implements ConcurrentMap<K,V> { 
    // The actual map holding the data. 
    Map<Integer, V> ordered = new ConcurrentSkipListMap<>(); 
    // Mapping the key to the order. 
    Map<K, Integer> reorder = new ConcurrentSkipListMap<>(); 
    // The next position. 
    AtomicInteger next = new AtomicInteger(0); 

    @Override 
    public V get(Object o) { 
    return ordered.get(reorder.get(o)); 
    } 

} 

你將不得不決定你需要的,如果你添加到同一個鍵兩次發生什麼。價值在哪個位置,原始位置還是新位置?原來的那個應該被刪除嗎?