Question

Is it possible in Guava,

  1. 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.

  2. 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.

Was it helpful?

Solution

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.

OTHER TIPS

The closest in Guava is Multiset to map multiple values to key, but I doubt it satisfies your requirement.

  1. I doubt it is good idea to look up key using values (when you have multiple values mapped to single key), in order to do this your value should be unique and considering your data structure (which is like Map<Key, Collection<Value>) it cannot be guaranteed to have unique values.
  2. The another option with guava is 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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top