Java Collection - Unique Key and Unique Value

The BiMap from Google Guava looks like it will suit you.

A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an "inverse view", which is another bimap containing the same entries as this bimap but with reversed keys and values.

Or the BidiMap from Apache Commons Collections:

Defines a map that allows bidirectional lookup between key and values.

This extended Map represents a mapping where a key may lookup a value and a value may lookup a key with equal ease. This interface extends Map and so may be used anywhere a map is required. The interface provides an inverse map view, enabling full access to both directions of the BidiMap.


You can use BiMap from Eclipse Collections (formerly GS Collections).

BiMap is a map that allows users to perform lookups from both directions. Both the keys and the values in a BiMap are unique.

The main implementation is HashBiMap.

inverse()

BiMap.inverse() returns a view where the position of the key type and value type are swapped.

MutableBiMap<Integer, String> biMap =
  HashBiMap.newWithKeysValues(1, "1", 2, "2", 3, "3");
MutableBiMap<String, Integer> inverse = biMap.inverse();
Assert.assertEquals("1", biMap.get(1));
Assert.assertEquals(1, inverse.get("1"));
Assert.assertTrue(inverse.containsKey("3"));
Assert.assertEquals(2, inverse.put("2", 4));

put()

MutableBiMap.put() behaves like Map.put() on a regular map, except it throws when a duplicate value is added.

MutableBiMap<Integer, String> biMap = HashBiMap.newMap();
biMap.put(1, "1"); // behaves like a regular put()
biMap.put(1, "1"); // no effect
biMap.put(2, "1"); // throws IllegalArgumentException

forcePut()

This behaves like MutableBiMap.put(), but it silently removes the map entry with the same value before putting the key-value pair in the map.

MutableBiMap<Integer, String> biMap = HashBiMap.newMap();
biMap.forcePut(1, "1"); // behaves like a regular put()
biMap.forcePut(1, "1"); // no effect
biMap.put(1, "2"); // replaces the [1,"1"] pair with [1, "2"]
biMap.forcePut(2, "2"); // removes the [1, "2"] pair before putting
Assert.assertFalse(biMap.containsKey(1));
Assert.assertEquals(HashBiMap.newWithKeysValues(2, "2"), biMap);

Note: I am a committer for Eclipse Collections.


The accepted answer mentions BiMap, but it's become more up-to-date with the Google Guava libraries.

A BiMap<K, V> is a Map<K, V> that

  • allows you to view the "inverse" BiMap<V, K> with inverse()
  • ensures that values are unique, making values() a Set

So, you can end up with code like this:

final BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("word", 1);
biMap.put("alpha", 2);
System.out.println(biMap.get("word")); // prints 1
System.out.println(biMap.inverse().get(1)); // prints word

Some caveats with this object:

  • You won't be able to add non-unique values, or you'll get an IllegalArgumentException. You can use forcePut(key, value), but that will override the existing key-value pair.