How to create a 2 way map in java
JavaData StructuresJava Problem Overview
I need a data structure to store string-int value pairs in an 1:1 relationship, and being able too look up from either way their counterpart.
I wrote a class with a Hashtable and a String array and stored the data 2 times and used the built in functions for lookup.
My question is that is there a nicer way to accomplish this? And by nicer I mean being efficient and not storing the data 2 times, and preferably without writing a ton of code either :P.
Java Solutions
Solution 1 - Java
It seems like you may be looking for a bimap.
The Google Collections (now a part of Guava) contains an BiMap
interface with a few implementations.
From the BiMap
documentation:
> 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.
The BiMap.inverse
method appears to return a Map
with the values as the keys, and the keys as the values, so that Map
can be used to call get
on the value and retrieve a key.
In addition the Map
returned by inverse
is a view of the underlying data, so it does not have to make extra copies of the original data.
From the BiMap.inverse
method documentation:
> Returns the inverse view of this > bimap, which maps each of this bimap's > values to its associated key. The two > bimaps are backed by the same data; > any changes to one will appear in the > other.
Solution 2 - Java
You can do a simple implementation like this. Please note that the data is not copied in this implementation. Only the references are ! I have added implementation for add and get. remove and other required method are left as exercise :)
public class TwoWayHashmap<K extends Object, V extends Object> {
private Map<K,V> forward = new Hashtable<K, V>();
private Map<V,K> backward = new Hashtable<V, K>();
public synchronized void add(K key, V value) {
forward.put(key, value);
backward.put(value, key);
}
public synchronized V getForward(K key) {
return forward.get(key);
}
public synchronized K getBackward(V key) {
return backward.get(key);
}
}
And ofcourse its applications responsibility to ensue even the 'values' are unique. Example usage:
TwoWayHashmap twmap = new TwoWayHashmap<String, String>();
twmap.add("aaa", "bbb");
twmap.add("xxx", "yyy");
System.out.println(twmap.getForward("xxx"));
System.out.println(twmap.getBackward("bbb"));
Solution 3 - Java
Apache Commons also includes the BidiMap (Bi Directional Map).
> 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.
Solution 4 - Java
Google Guava has a BiMap that does what you want.
Solution 5 - Java
Using Guava,
HashBiMap<String, String> map = HashBiMap.create();
map.put("name", "Sohail");
map.put("country", "Pakistan");
Log.d("tag", "name is " + map.get("name"));
BiMap<String, String>invmap= map.inverse();
Log.d("tag", "Pakistan is a " + invmap.get("Pakistan"));
read complete tutorial here.
Solution 6 - Java
definitely w/o writing a ton of code → in lambda
from Your Map<String,Integer> map
You get the inverted map by
Map<Integer,String> inverted = map.keySet().stream().collect(Collectors.toMap( s -> map.get( s ), s -> s ) );
Solution 7 - Java
Create a hashmap that maps Object to Object - then you can use the same map to store String -> Integer and Integer -> String.
When you add a string/int pair just add it both ways to the same map.