Two Way Mapping using single Data Structure
Question
I ran across some code recently at work (recreated to be similar to what I am dealing with) similar to the code below
Is there a way I can rework the code below to use one data structure (with performance in mind)?
Here is some code to illustrate what I mean:
public class ObjectMapper {
private Map<UUID,Integer> uuidMap;
private Map<Integer,UUID> indexMap;
public ObjectMapper(){
uuidMap = new HashMap<UUID,Integer>();
indexMap = new HashMap<Integer,UUID>();
}
public void addMapping(int index, UUID uuid){
uuidMap.put(uuid, index);
indexMap.put(index, uuid);
}
.
.
.
public Integer getIndexByUUID(UUID uuid){
return uuidMap.get(uuid);
}
public UUID getUUIDByIndex(Integer index){
return indexMap.get(index);
}
}
Solution
This is answered here with the recommendation to use BiMap from Google Collections
OTHER TIPS
Apache collections supports a BidiMap interface and a variety of fairly effective implementations.
You could use a single Map<Object,Object>
to do both mappings. Ugly, sure. Performance should be roughly the same, or slightly better in the unlikely event that you have many ObjectMapper
s with few mapped values.
You can use BiMap from Eclipse 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.forcePut(1, "2"); // replaces the [1,"1"] pair with [1, "2"]
biMap.put(2, "2"); // removes the [1, "2"] pair before putting
Assert.assertFalse(biMap.containsKey(1));
Assert.assertEquals(HashBiMap.newWithKeysValues(2, "1"), biMap);
Note: I am a committer for Eclipse collections.