001/*
002 * Copyright 2021 Global Biodiversity Information Facility (GBIF)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.gbif.utils.collection;
017
018import java.util.Collections;
019import java.util.Comparator;
020import java.util.LinkedHashMap;
021import java.util.LinkedList;
022import java.util.List;
023import java.util.Map;
024
025public class MapUtils {
026
027  private MapUtils() {
028    throw new UnsupportedOperationException("Can't initialize class");
029  }
030
031  /**
032   * This orders a Map by its values and returns a new {@link LinkedHashMap} which maintains that order.
033   *
034   * @param map to sort
035   * @param <K> type of the map key
036   * @param <V> type of the map value, this needs to implement {@link Comparable}
037   *
038   * @return a map ordered by the values of the input map
039   */
040  public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
041    return sortByValueInternal(map, new Comparator<Map.Entry<K, V>>() {
042      @Override
043      public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
044        return o1.getValue().compareTo(o2.getValue());
045      }
046    });
047  }
048
049  /**
050   * Order a Map by its values using the given value comparator and return a new {@link LinkedHashMap} which maintains that order.
051   *
052   * @param map to sort
053   * @param <K> type of the map key
054   * @param <V> type of the map value
055   *
056   * @return a map ordered by the values of the input map
057   */
058  public static <K, V> Map<K, V> sortByValue(Map<K, V> map, final Comparator<V> comparator) {
059    return sortByValueInternal(map, new Comparator<Map.Entry<K, V>>() {
060        @Override
061        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
062          return comparator.compare(o1.getValue(), o2.getValue());
063        }
064      });
065  }
066
067  private static <K, V> Map<K, V> sortByValueInternal(Map<K, V> map, final Comparator<Map.Entry<K, V>> comp) {
068    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
069    Collections.sort(list, comp);
070
071    Map<K, V> result = new LinkedHashMap<K, V>(list.size());
072    for (Map.Entry<K, V> entry : list) {
073      result.put(entry.getKey(), entry.getValue());
074    }
075    return result;
076  }
077
078  /**
079   * Returns a maps value or a given default if not present.
080   * For pre java8 code since j8 introduced Map.getOrDefault.
081   */
082  public static <K, V> V getOrDefault(Map<K,V> map, K key, V defaultValue) {
083    return map.containsKey(key) ? map.get(key) : defaultValue;
084  }
085}