Hot questions for Operating Map in Guava

Top 10 Java Open Source / Guava / Operating Map

Map that could be iterated in the order of values

Question: I need a Map that could be iterated in the decreasing order of its values. Does any of the standard libraries like Apache Commons or Guava provide this kind of map?

Answer: I would do this with Guava as follows:

Ordering<Map.Entry<Key, Value>> entryOrdering = Ordering.from(valueComparator)
  .onResultOf(new Function<Entry<Key, Value>, Value>() {
    public Value apply(Entry<Key, Value> entry) {
      return entry.getValue();
    }
  }).reverse();
// Desired entries in desired order.  Put them in an ImmutableMap in this order.
ImmutableMap.Builder<Key, Value> builder = ImmutableMap.builder();
for (Entry<Key, Value> entry : 
    entryOrdering.sortedCopy(map.entrySet())) {
  builder.put(entry.getKey(), entry.getValue());
}
return builder.build();
// ImmutableMap iterates over the entries in the desired order

How to do map inversion with Guava with non-unique values?

Question: How can we do that with Guava? Notice the presence of List<K> in the return type since many keys can map to the same value in any normal map.

public static <K, V> Map<V, List<K>> inverse(Map<K, V> map){
    Map<V, List<K>> result = new LinkedHashMap<V, List<K>>();
    for (Map.Entry<K, V> entry : map.entrySet()) {
        if(!result.containsKey(entry.getValue())){
            result.put(entry.getValue(), new ArrayList<K>());                
        }
        result.get(entry.getValue()).add(entry.getKey());
    }        
    return result;        
}

BiMap seems to insist on the unicity of the values, but I don't have this luxury.

Answer: You can do this:

Map<K, V> map = ...;
ListMultimap<V, K> inverse = Multimaps.invertFrom(Multimaps.forMap(map), 
    ArrayListMultimap.<V,K>create());

Do note that pretty much any time you write Map<K, List<V>> or Map<K, Set<V>> or some such, a ListMultimap<K, V> or SetMultimap<K, V> is what you really want.


Get minvalue of a Map(Key,Double)

Question: Is there a method (maybe with Google Collections) to obtain the min value of a Map(Key, Double)?

In the traditional way, I would have to sort the map according to the values, and take the first/last one.

Answer: You can use the standard Collections#min() for this.

Map<String, Double> map = new HashMap<String, Double>();
map.put("1.1", 1.1);
map.put("0.1", 0.1);
map.put("2.1", 2.1);

Double min = Collections.min(map.values());
System.out.println(min); // 0.1

since you need the key as well, well, I don't see ways in Collections or Google Collections2 API since a Map is not a Collection. The Maps#filterEntries() is also not really useful, since you only know the actual result at end of iteration.

Most straightforward solution would then be this:

Entry<String, Double> min = null;
for (Entry<String, Double> entry : map.entrySet()) {
    if (min == null || min.getValue() > entry.getValue()) {
        min = entry;
    }
}

System.out.println(min.getKey()); // 0.1

Get all Values from a Map for some Keys in Java/Guava?

Question: Is there a smart way to get all Values from a Map given some Keys?

I would like a method like this:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys)
System.out.println(min.getKey()); // 0.1

or is already a guava way?

Answer: for Guava version:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) {
    return Maps.filterKeys(map, Predicates.in(keys)).values();
}

Also, here's a non-Guava version:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) {
    Map<K, V> newMap = new HashMap<K, V>(map);
    newMap.keySet().retainAll(keys);
    return newMap.values();
}