2017-06-02 70 views
2

我需要双密钥并发hashmap。关于java中的双密钥并发hashmap

我的第一次尝试就是使用java.util.concurrent.ConcurrentHashMap。像这样

ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); 
map.put("key1" + "|" +"key2", "value"); 
String vaule = map.get("key1" + "|" +"key2"); 

但我觉得这很丑。

我的第二次尝试是使用对象作为关键。像这样

@Data 
public class DualKey { 
    private final String key1; 
    private final String key2; 
} 
map.put(new DualKey("key1", "key2"), "value"); 
String vaule = map.get(new DualKey("key1", "key2")); 

最后一次尝试是创建DualkeyConcurrentHashMap。我只需要放置,获取,containsKey。

public class DualkeyConcurrentHashMap<K1, K2, V> { 
    private final ConcurrentHashMap<K1, ConcurrentHashMap<K2, V>> map 
                = new ConcurrentHashMap<>(); 

    public V put(K1 key1, K2 key2, V value) { 
     ConcurrentHashMap<K2, V> subMap 
        = map.computeIfAbsent(key1, k -> new ConcurrentHashMap<>()); 
     return subMap.put(key2, value); 
    } 

    public V get(K1 key1, K2 key2) { 
     ConcurrentHashMap<K2, V> subMap = map.get(key1); 
     return null == subMap ? null : subMap.get(key2); 
    } 

    public boolean containsKey(K1 key1, K2 key2) { 
     return null != get(key1, key2); 
    } 
} 

它是更好的和完美的线程安全吗? (我不能决定所有的方法需要同步。)

有没有另一种推荐的方法?

+0

正如你已经有(可能)所有解决方案的工作代码,执行一个基准 - 你会看到是否有任何差异,你会回答你的问题。喜欢看结果。 – Antoniossss

+1

我不喜欢价值对象的方法,因为你必须创建对象只是为了从地图获得价值 – SHaaD

+1

第一个选项实际上并不适用于所有的键:它会得到相同的值为'“a”,“b | c“'和''a | b”,“c”'。 –

回答

3

All options are thread-safe,由ConcurrentHashMap担保。重要fact to note is

不过,尽管所有操作都是线程安全的,检索 操作不意味着锁定,并没有对 锁定整个表以防止所有访问的方式提供任何支持。该类 与依赖其线程安全性但不同步详细信息的程序中的Hashtable完全可互操作。

实现双关键映射的自然方法是提供一个对象,所以我会去第二个对象,只是我会让DualKey泛型。

第一个配对实现和设计(string1 "|" + string1密钥格式)并且不允许您轻松更改用作密钥的类型。

第三个使用ConcurrentHashMap比需要更多的实例。