Reputation: 9349
Can you suggest a kind of map or similar data structure where we can get both the value and key from each other at equal ease. That is to say, that each may be used to find other.
Upvotes: 71
Views: 29619
Reputation: 818
Based on this tutorial I suggest the following as answer:
public class IdToNames {
public static void main(String[] args){
BidiMap<String, Integer> map = new DualHashBidiMap<>();
map.put("NameA", 100);
map.put("NameB", 200);
System.out.println(map.size()); //2 as expected
System.out.println(map.get("NameA")); //100 as expected
System.out.println(map.getKey(100)); //"NameA" as expected
}
}
Note the problem of duplicated keys and/or values described in this question here
Upvotes: 1
Reputation: 5756
Based on this answer in this QA and its comments I wrote following. [Will be tested]
Bidirectional Map
import java.util.HashMap;
public class BidirectionalMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
public HashMap<V, K> inversedMap = new HashMap<V, K>();
public K getKey(V value) {
return inversedMap.get(value);
}
@Override
public int size() {
return this.size();
}
@Override
public boolean isEmpty() {
return this.size() > 0;
}
@Override
public V remove(Object key) {
V val=super.remove(key);
inversedMap.remove(val);
return val;
}
@Override
public V get(Object key) {
return super.get(key);
}
@Override
public V put(K key, V value) {
inversedMap.put(value, key);
return super.put(key, value);
}
}
Upvotes: 3
Reputation: 11
You can define an enum and define helper method to get key. Performance is way too far better compared to BidiMap. E.g
public enum Fruit {
APPLE("_apple");
private final String value;
Fruit(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
public static String getKey(String value){
Fruit fruits[] = Fruit.values();
for(Fruit fruit : fruits){
if(value.equals(fruit.value)){
return fruit.name();
}
}
return null; }
}
Upvotes: 0
Reputation: 206996
Java doesn't have a bidirectional map in its standard library.
Use for example BiMap<K, V>
from Google Guava .
Upvotes: 49
Reputation: 13825
If you feel it pain importing some third party library. How about this simple class.
public class BiMap<K,V> {
HashMap<K,V> map = new HashMap<K, V>();
HashMap<V,K> inversedMap = new HashMap<V, K>();
void put(K k, V v) {
map.put(k, v);
inversedMap.put(v, k);
}
V get(K k) {
return map.get(k);
}
K getKey(V v) {
return inversedMap.get(v);
}
}
Make sure K and V class has proper hashCode implementation.
Upvotes: 37
Reputation: 1296
well for the average usecase where you need a Dictionary like that, I see nothing wrong with a KISS solution, just put'ting the key and value vice versa, saving the overhead of a second Map or even library only for that purpose:
myMap.put("apple", "Apfel");
myMap.put("Apfel", "apple");
Upvotes: 4
Reputation: 111389
The most common solution is using two maps. You can easily encapsulate them in a class with a friendly interface by extending AbstractMap
. (Update: This is how Guava's HashBiMap
is implemented: two maps)
Creating a new data structure using nothing but arrays and custom classes has few advantages. The map implementations are lightweight wrappers of a data structure that indexes the keys. Since you need two indexes you might as well use two complete maps.
Upvotes: 14