2

I need dual key concurrent hashmap.

My first try is just using java.util.concurrent.ConcurrentHashMap. Like this

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

but I think this is ugly.

My Second try is using Object as Key. Like this

@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"));

Last try is create DualkeyConcurrentHashMap. I just need put, get, 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);
    }
}

Is it better and perfectly thread safe? (I can't decide all method need synchronized.)

Is there another recommended way?

KI-YOUNG BANG
  • 199
  • 1
  • 10
  • As you already have (probably) working code for all solutions, perform a benchmark - you will see if there are any differences and you will answer your question. Love to see results. – Antoniossss Jun 02 '17 at 06:32
  • 1
    I don't like value object approach, cuz you have to create object just to get value from map – SHaaD Jun 02 '17 at 06:36
  • 1
    The first option doesn't actually work for all keys: it would get the same value for `"a", "b|c"` and for `"a|b", "c"`. – Alexey Romanov Jun 02 '17 at 07:19
  • 1
    `Arrays.asList(key1, key2)` provides you with an a working key. You have to care not to modify that object, but it’s concise and can easily replaced with Java 9‘s `List.of(key1, key2)` which gives you an immutable key. – Holger Jun 02 '17 at 16:31

1 Answers1

3

All options are thread-safe, which is guaranteed by ConcurrentHashMap. Important fact to note is:

However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.

The natural way to implement a dual key map would be to provide an object, so I would go with the second one, only that I would make DualKey generic.

The first one couples implementation and design (string1 "|" + string1 key format) and does not allow you to change types used as keys easily.

The third one uses much more instances of ConcurrentHashMap than needed.

syntagma
  • 23,346
  • 16
  • 78
  • 134