Reputation: 81
I'm back again with a similar question. Is there a DataType that can return its specific partner? For example:
ExampleType<String,String> test = new ExampleType<String,String>();
test.put("hello","hi");
If I were to type test.get("hi"), it would return "hello", and if I were to type test.get("hello"), it would return "hi".
My only guess for this would maybe be a two dimensional array, but I'm not sure how I would implement this. As of right now, the only way I can understand of doing this is creating two different hashmaps and swapping the keys in each. (obviously this is not very efficient/effective).
Thanks for all the help!
Upvotes: 5
Views: 304
Reputation: 23465
Nothing built in, so you either use a 3rd party package like Guava's BiMap mentioned by Pangea, or, if you want to roll your own, if you need two distinct data types, the 2-maps idea is not bad, if your keys and values are the same type you can use a single map with doubled entries:
public class BiMap<T>{
private Map<T,T> theMap = new HashMap<T,T>();
public void put( T key, T value ){ put( key, value, false ); }
public void forcePut( T key, T value ){ put( key, value, true ); }
private void put( T key, T value, boolean force ){
if( force || !theMap.containsKey(value) ){
theMap.remove( theMap.remove( key ) );
theMap.put( key, value );
theMap.put( value, key );
}else if( !theMap.get( value ).equals( key ) ){
// If you allow null values&keys this will get more complicated.
throw new IllegalArgumentException();
// can make this more informative.
}
// else the pair is already in, there's nothing to do.
}
public T get( T key ){ return theMap.get( key ); }
public T remove( T key ){
T value = theMap.remove( key );
if( value != null ) theMap.remove( value );
return value;
}
}
Notice that because everything is an object, there isn't much waste as far as efficiency/space is concerned: the only things you're storing twice are object addresses. The same goes for your 2-map idea.
Also it wouldn't be too hard to add the necessary methods to make this implement the Map<T,T>
interface for compliance's sake.
Upvotes: 3
Reputation: 57284
Assuming you aren't intending to distinguish which part of the pair you're querying for (that is, you want to see
test.get("hi") => "hello"
test.get("hello") => "hi"
why not just insert both keys into the same map?
test.put("hello","hi");
test.put("hi","hello");
Upvotes: 0
Reputation: 15766
Two ArrayLists would probably be the easiest.. Just make sure you store the pairs in the same index and it should work fine. Code would look something like:
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
list1.add("hi");
list2.add("hello");
get("hi");
and your get method:
get(String s){
return list2.get( list1.indexOf(s) );
}
Don't know if this is the best solution, but it is a solution.
Upvotes: -1
Reputation: 80176
You can use the Guava's BiMap for this. It supports inverse lookup as well:
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.
If you already have a dependency on commons-collections then you can also use BidiMap
.
Upvotes: 10