不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2022-06-23 00:23:56  修改时间:2024-04-23 03:09:29  分类:Java基础  编辑

网摘1:Java Map排序

在实际业务开发中,可能会遇到Java Map按值排序的需要。

Java Map按值排序的常见思路是

  1. 将Map中的Entry放到List中
  2. 对List中的Entry通过比较器按值排序
  3. 将排序后的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
                        )
                );
    }

}