网摘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
)
);
}
}