网摘1:Java Map排序
在实际业务开发中,可能会遇到Java Map按值排序的需要。
Java Map按值排序的常见思路是:
- 将Map中的Entry放到List中
- 对List中的Entry通过比较器按值排序
- 将排序后的Entry放到LinkedHashMap中
Java 8利用Stream
import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import static java.util.Map.Entry.comparingByValue; import static java.util.stream.Collectors.toMap; public class SortTest { public static void main(String[] args) throws Exception { // 创建一个字符串为Key,数字为值的map Map<String, Integer> budget = new HashMap<>(); budget.put("clothes", 120); budget.put("grocery", 150); budget.put("transportation", 100); budget.put("utility", 130); budget.put("rent", 1150); budget.put("miscellneous", 90); System.out.println("排序前: " + budget); // 按值排序 升序 Map<String, Integer> sorted = budget .entrySet() .stream() .sorted(comparingByValue()) .collect( toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new)); System.out.println("升序按值排序后的map: " + sorted); // 按值排序降序 sorted = budget .entrySet() .stream() .sorted(Collections.reverseOrder(comparingByValue())) .collect( toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new)); System.out.println("降序按值排序后的map: " + sorted); } }
可以封装成工具类
/** * Map排序工具类 */ public class MapSortUtil { private static Comparator<Map.Entry> comparatorByKeyAsc = (Map.Entry o1, Map.Entry o2) -> { if (o1.getKey() instanceof Comparable) { return ((Comparable) o1.getKey()).compareTo(o2.getKey()); } throw new UnsupportedOperationException("键的类型尚未实现Comparable接口"); }; private static Comparator<Map.Entry> comparatorByKeyDesc = (Map.Entry o1, Map.Entry o2) -> { if (o1.getKey() instanceof Comparable) { return ((Comparable) o2.getKey()).compareTo(o1.getKey()); } throw new UnsupportedOperationException("键的类型尚未实现Comparable接口"); }; private static Comparator<Map.Entry> comparatorByValueAsc = (Map.Entry o1, Map.Entry o2) -> { if (o1.getValue() instanceof Comparable) { return ((Comparable) o1.getValue()).compareTo(o2.getValue()); } throw new UnsupportedOperationException("值的类型尚未实现Comparable接口"); }; private static Comparator<Map.Entry> comparatorByValueDesc = (Map.Entry o1, Map.Entry o2) -> { if (o1.getValue() instanceof Comparable) { return ((Comparable) o2.getValue()).compareTo(o1.getValue()); } throw new UnsupportedOperationException("值的类型尚未实现Comparable接口"); }; /** * 按键升序排列 */ public static <K, V> Map<K, V> sortByKeyAsc(Map<K, V> originMap) { if (originMap == null) { return null; } return sort(originMap, comparatorByKeyAsc); } /** * 按键降序排列 */ public static <K, V> Map<K, V> sortByKeyDesc(Map<K, V> originMap) { if (originMap == null) { return null; } return sort(originMap, comparatorByKeyDesc); } /** * 按值升序排列 */ public static <K, V> Map<K, V> sortByValueAsc(Map<K, V> originMap) { if (originMap == null) { return null; } return sort(originMap, comparatorByValueAsc); } /** * 按值降序排列 */ public static <K, V> Map<K, V> sortByValueDesc(Map<K, V> originMap) { if (originMap == null) { return null; } return sort(originMap, comparatorByValueDesc); } private static <K, V> Map<K, V> sort(Map<K, V> originMap, Comparator<Map.Entry> comparator) { return originMap.entrySet() .stream() .sorted(comparator) .collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new)); } }
测试:
package com.chujianyun.common.map; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import java.util.HashMap; import java.util.Map; /** * Map排序工具类 */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MapSortUtilTest { // 创建一个字符串为Key,数字为值的map Map<String, Integer> budget = new HashMap<>(); @BeforeAll public void init() { budget.put("clothes", 120); budget.put("grocery", 150); budget.put("transportation", 100); budget.put("utility", 130); budget.put("rent", 1150); budget.put("miscellneous", 90); System.out.println("排序前: " + budget); } @Test void sortByKeyAsc() { System.out.println("按键升序" + MapSortUtil.sortByKeyAsc(budget)); } @Test void sortByKeyDesc() { System.out.println("按键降序" + MapSortUtil.sortByKeyDesc(budget)); } @Test void sortByValueAsc() { System.out.println("按值升序" + MapSortUtil.sortByValueAsc(budget)); } @Test void sortByValueDesc() { System.out.println("按值降序" + MapSortUtil.sortByValueDesc(budget)); } }
Java 7版本
import java.util.*; import java.lang.*; public class GFG { // hashmap按值排序 public static HashMap<String, Integer> sortByValue(HashMap<String, Integer> hm) { // HashMap的entry放到List中 List<Map.Entry<String, Integer> > list = new LinkedList<Map.Entry<String, Integer> >(hm.entrySet()); // 对List按entry的value排序 Collections.sort(list, new Comparator<Map.Entry<String, Integer> >() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 ) { return (o1.getValue()).compareTo(o2.getValue()); } }); // 将排序后的元素放到LinkedHashMap中 HashMap<String, Integer> temp = new LinkedHashMap<String, Integer>(); for (Map.Entry<String, Integer> aa : list) { temp.put(aa.getKey(), aa.getValue()); } return temp; } public static void main(String[] args) { HashMap<String, Integer> hm = new HashMap<String, Integer>(); // 填充测试数据 hm.put("Math", 98); hm.put("Data Structure", 85); hm.put("Database", 91); hm.put("Java", 95); hm.put("Operating System", 79); hm.put("Networking", 80); Map<String, Integer> hm1 = sortByValue(hm); // 打印按值排序后的数据 for (Map.Entry<String, Integer> en : hm1.entrySet()) { System.out.println("Key = " + en.getKey() + ", Value = " + en.getValue()); } } }
网摘2:Map排序工具类(正序/倒序)
/** * map工具类 * **/ public class MyMapUtils { /** * 根据map的key排序 * @methodName orderByKey * @param map 原始map * @param isDesc 是否降序 * @return java.util.Map<K,V> */ public static <K extends Comparable<? super K>, V extends Comparable<? super V>> Map<K, V> orderByKey(Map<K, V> map, boolean isDesc) { if (CollectionUtil.isEmpty(map)) { return map; } Map<K, V> result = Maps.newLinkedHashMapWithExpectedSize(map.size()); if (isDesc) { map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed()) .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); } else { map.entrySet().stream().sorted(Map.Entry.comparingByKey()) .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); } return result; } /** * 根据map的value排序 * @methodName orderByValue * @param map 原始map * @param isDesc 是否降序 * @return java.util.Map<K,V> */ public static <K extends Comparable<? super K>, V extends Comparable<? super V>> Map<K, V> orderByValue(Map<K, V> map, boolean isDesc) { if (CollectionUtil.isEmpty(map)) { return map; } Map<K, V> result = Maps.newLinkedHashMapWithExpectedSize(map.size()); if (isDesc) { map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue().reversed()) .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); } else { map.entrySet().stream().sorted(Map.Entry.comparingByValue()) .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); } return result; } public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); map.put(2, "a"); map.put(1, "b"); map.put(3, "c"); map.put(5, "d"); map.put(4, "e"); System.out.println("输入>>>>>>>>>"+map); Map<Integer, String> kMap = orderByKey(map, true); System.out.println("key倒序>>>>>>>>>"+kMap); Map<Integer, String> vMap = orderByValue(map, false); System.out.println("value正序>>>>>>>>>"+vMap); } }
网摘3:JDK8源码,在Map接口下:
/Applications/jdk-17.0.2.jdk/Contents/Home/lib/src.zip!/java.base/java/util/Map.java
/** * Returns a comparator that compares {@link Map.Entry} in natural order on key. * * <p>The returned comparator is serializable and throws {@link * NullPointerException} when comparing an entry with a null key. * * @param <K> the {@link Comparable} type of then map keys * @param <V> the type of the map values * @return a comparator that compares {@link Map.Entry} in natural order on key. * @see Comparable * @since 1.8 */ public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey()); } /** * Returns a comparator that compares {@link Map.Entry} in natural order on value. * * <p>The returned comparator is serializable and throws {@link * NullPointerException} when comparing an entry with null values. * * @param <K> the type of the map keys * @param <V> the {@link Comparable} type of the map values * @return a comparator that compares {@link Map.Entry} in natural order on value. * @see Comparable * @since 1.8 */ public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getValue().compareTo(c2.getValue()); }
综上所述,整理出自己的一个Map排序工具类:
package com.wanma.framework_web.helper; import java.io.Serializable; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; /** * Map 助手类 * 参考:/2262.html */ public class MapHelper { private static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparatorByKeyAsc() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey()); } private static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparatorByKeyDesc() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c2.getKey().compareTo(c1.getKey()); } private static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparatorByValueAsc() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getValue().compareTo(c2.getValue()); } private static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparatorByValueDesc() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c2.getValue().compareTo(c1.getValue()); } /** * 按键升序排列 */ public static <K extends Comparable<? super K>, V> Map<K, V> sortByKeyAsc(Map<K, V> originMap) { if (originMap == null) { return null; } return originMap.entrySet() .stream() .sorted(comparatorByKeyAsc()) .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new ) ); } /** * 按键降序排列 */ public static <K extends Comparable<? super K>, V> Map<K, V> sortByKeyDesc(Map<K, V> originMap) { if (originMap == null) { return null; } return originMap.entrySet() .stream() .sorted(comparatorByKeyDesc()) .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new ) ); } /** * 按值升序排列 */ public static <K, V extends Comparable<? super V>> Map<K, V> sortByValueAsc(Map<K, V> originMap) { if (originMap == null) { return null; } return originMap.entrySet() .stream() .sorted(comparatorByValueAsc()) .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new ) ); } /** * 按值降序排列 */ public static <K, V extends Comparable<? super V>> Map<K, V> sortByValueDesc(Map<K, V> originMap) { if (originMap == null) { return null; } return originMap.entrySet() .stream() .sorted(comparatorByValueDesc()) .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new ) ); } }