Reputation: 3858
Is it possible in Guava,
To conduct a reverse lookup in BiMap
for key and multiple values? Precisely, I have key and corresponding multiple values, I want to get key from a value.
To store multiple values in LinkedHashMap
? Precisely, I want to store, key - multiple values in some order thus I can get key position in the list.
Upvotes: 2
Views: 2811
Reputation: 28005
Ad. 1. Yes, it's possible to do a reverse lookup with a BiMap<K, V>
, you just call inverse
on your BiMap
and you get inversed BiMap<V, K>
view of your BiMap
.
Example (taken from Guava's test suite):
public void testMapConstructor() {
/* Test with non-empty Map. */
Map<String, String> map = ImmutableMap.of(
"canada", "dollar",
"chile", "peso",
"switzerland", "franc");
HashBiMap<String, String> bimap = HashBiMap.create(map);
assertEquals("dollar", bimap.get("canada"));
assertEquals("canada", bimap.inverse().get("dollar"));
}
Ad. 2. Assuming you mean "I want to store, key -> multiple [collection] values" (Map<K, Collection<V>>
), ListMultimap
is probably what you want, more precisly ArrayListMultimap
(preserves values order) or LinkedListMultimap
(preserves both keys and values order). If your object is going to be immutable, I strongly advice you use ImmutableListMultimap
.
You can also create your own implementation of Multimap
by using factory (bit verbose), i.e. I use:
private static <K, V> ListMultimap<K, V> makeLinkedArrayListMultimap() {
return Multimaps.newListMultimap(Maps.<K, Collection<V>>newLinkedHashMap(),
new Supplier<List<V>>() {
@Override public List<V> get() {
return Lists.newArrayList();
}
});
}
public static void main(final String[] args) {
final ListMultimap<String, String> multimap = makeLinkedArrayListMultimap();
multimap.putAll("one", ImmutableList.of("zero", "three"));
multimap.putAll("two", ImmutableList.of("three", "four", "three"));
multimap.putAll("three", ImmutableList.<String>of()); // note that this doesn't add key to multimap
multimap.put("four", "forty-two");
System.out.println(multimap);
// prints {one=[one, three], two=[three, four, three], four=[forty-two]}
final List<String> listForOnes = multimap.get("one");
System.out.println(listForOnes.get(0));
// prints zero
}
P.S. Take a look at Guava's wiki, which is explaining both BiMap
and Multimap
.
Upvotes: 8
Reputation: 110054
As @Xaerxess says in his answer to your 2nd question, you can make your own ListMultimap
that uses a LinkedHashMap
as its backing map using the Multimaps.newListMultimap
method.
For your 1st question, where you have keys mapped to multiple values (i.e. a Multimap
), you can use the method Multimaps.invertFrom
to create an inverted copy of your original Multimap
to do inverse lookups on. Also, you can create an ImmutableListMultimap
copy of the original and use its inverse()
method to get the inverse, though that's just going to copy the original just like Multimaps.invertFrom
does (though it will cache it so repeated calls to inverse()
return the same copy.)
This is likely worth it if you don't mind the extra memory consumption, are going to want to do multiple inverse lookups, and don't need the inverse copy to stay up to date with changes to the original that happen after you create it. If you just want to lookup the keys that map to one specific value, you can do that in one iteration of the entries without creating a full copy.
Upvotes: 3
Reputation: 7902
The closest in Guava is Multiset
to map multiple values to key, but I doubt it satisfies your requirement.
Map<Key, Collection<Value>
) it cannot be guaranteed to have unique values.BiMap
which requires unique values and can provide a reverse mappings (value -> key) but since you need to map multiple values to same key, this also not a good fit. Upvotes: 3