001package org.gbif.utils.collection;
002
003import java.util.Collections;
004import java.util.Comparator;
005import java.util.LinkedHashMap;
006import java.util.LinkedList;
007import java.util.List;
008import java.util.Map;
009
010public class MapUtils {
011
012  private MapUtils() {
013    throw new UnsupportedOperationException("Can't initialize class");
014  }
015
016  /**
017   * This orders a Map by its values and returns a new {@link LinkedHashMap} which maintains that order.
018   *
019   * @param map to sort
020   * @param <K> type of the map key
021   * @param <V> type of the map value, this needs to implement {@link Comparable}
022   *
023   * @return a map ordered by the values of the input map
024   */
025  public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
026    return sortByValueInternal(map, new Comparator<Map.Entry<K, V>>() {
027      public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
028        return o1.getValue().compareTo(o2.getValue());
029      }
030    });
031  }
032
033  /**
034   * Order a Map by its values using the given value comparator and return a new {@link LinkedHashMap} which maintains that order.
035   *
036   * @param map to sort
037   * @param <K> type of the map key
038   * @param <V> type of the map value
039   *
040   * @return a map ordered by the values of the input map
041   */
042  public static <K, V> Map<K, V> sortByValue(Map<K, V> map, final Comparator<V> comparator) {
043    return sortByValueInternal(map, new Comparator<Map.Entry<K, V>>() {
044        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
045          return comparator.compare(o1.getValue(), o2.getValue());
046        }
047      });
048  }
049
050  private static <K, V> Map<K, V> sortByValueInternal(Map<K, V> map, final Comparator<Map.Entry<K, V>> comp) {
051    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
052    Collections.sort(list, comp);
053
054    Map<K, V> result = new LinkedHashMap<K, V>(list.size());
055    for (Map.Entry<K, V> entry : list) {
056      result.put(entry.getKey(), entry.getValue());
057    }
058    return result;
059  }
060
061  /**
062   * Returns a maps value or a given default if not present.
063   * For pre java8 code since j8 introduced Map.getOrDefault.
064   */
065  public static <K, V> V getOrDefault(Map<K,V> map, K key, V defaultValue) {
066    return map.containsKey(key) ? map.get(key) : defaultValue;
067  }
068}