• 又双叒叕一行代码:Map按值排序


    分段随机实践—模拟线上流量一文中,我将流量模型统计成为一个个Map<F, Integer>形式数据保存起来。

    由于HashMap本身是无序的,我希望能够按照各个流量模型的value值进行排序输出,所以我又开始了学习Java的短暂旅途。

    没想到除了java一行代码打印心形以外,又发现了一行代码。

    LinkedHashMap

    我自己最常用的HashMap。HashMap是一种非常常见、非常有用的集合,但在多线程情况下使用不当会有线程安全问题。

    所以通常情况下只要不涉及线程安全问题,Map基本都可以使用HashMap,不过HashMap本身是一个无序的,不会记录每一个Entry数据插入的次序。

    LinkedHashMap就闪亮登场了,它虽然增加了时间和空间上的开销,但是通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序。

    基础写法

    这是一个比较基础的写法,思路是先将HashMap转换成List<Map.Entry>数据,然后使用Collections.sort方法进行排序,然后重新添加到LinkedHashMap集合对象当中。

    
    public class Map_FunTester extends SourceCode {
    
        public static void main(String[] args) {
            Map<String, Integer> hashMap = new HashMap<>();
            hashMap.put("fun", 3);
            hashMap.put("funtest", 7);
            hashMap.put("funtester", 9);
            hashMap.put("f", 1);
            output(hashMap);
            List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(hashMap.entrySet());
            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() - o2.getValue();
                }
            });
            Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
            for (Map.Entry<String, Integer> entry : list) {
                linkedHashMap.put(entry.getKey(), entry.getValue());
            }
            output(linkedHashMap);
        }
    
    }
    
    

    控制台输出:

    INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
    INFO-> 
    +-----------+---+
    |     f     | 1 |
    |  funtest  | 7 |
    | funtester | 9 |
    |    fun    | 3 |
    +-----------+---+
    INFO-> 
    +-----------+---+
    |     f     | 1 |
    |    fun    | 3 |
    |  funtest  | 7 |
    | funtester | 9 |
    +-----------+---+
    
    Process finished with exit code 0
    

    Lambda写法

    其实这个功能完全可以使用Lambda写法来简化整个过程。如下:

            LinkedHashMap<String, Integer> linkedHashMap = hashMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1 + v2, LinkedHashMap::new));
            output(linkedHashMap);
    

    哈哈,又是一行代码创造的奇迹。

    这个Lambda写法的重点就在于Collectors.toMapCollectors.toMap有三个重载方法:

    toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
    toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
            BinaryOperator<U> mergeFunction);
    toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
            BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);
    

    其中四个参数解释如下:

    1. keyMapper:Key 的映射函数
    2. valueMapper:Value 的映射函数
    3. mergeFunction:当 Key 冲突时,调用的合并方法
    4. mapSupplier:Map 构造器,在需要返回特定的 Map 时使用

    虽然从HashMap获取keys的时候不会出现重复,但是最后一个参数是mapSupplier,必须使用toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);这个构造方法。

    控制台输出:

    如上
    

    适用拓展

    Collectors.toMap最常用的地方还说将List转换成Map数据常用。例子如下:

        public static void main(String[] args) {
            List<String> list = Arrays.asList("f", "fun", "funtest", "funtester");
            Map<String, Integer> collect = list.stream().collect(Collectors.toMap(f -> f, f -> f.length(), (v1, v2) -> v2));
            output(collect);
        }
    

    控制台输出:

    INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
    INFO-> 
    +-----------+---+
    |     f     | 1 |
    |  funtest  | 7 |
    | funtester | 9 |
    |    fun    | 3 |
    +-----------+---+
    
    Process finished with exit code 0
    
    

    Have Fun ~ Tester !

    FunTester腾讯云年度作者Boss直聘签约作者GDevOps官方合作媒体,非著名测试开发,欢迎关注。

    点击阅读阅文,查看FunTester历史原创集合

  • 相关阅读:
    Oracle
    Oracle
    Oracle
    PTA | 1012 数字分类 (20分)
    PTA | 1010 一元多项式求导 (25分)
    PTA | 1009说反话(20分)
    PTA | 1008 数组元素循环右移问题 (20分)
    PTA | 1005 继续(3n+1)猜想 (25分)
    LeetCode 题解 | 70. 爬楼梯
    LeetCode 题解 | 242. 有效的字母异位词
  • 原文地址:https://www.cnblogs.com/FunTester/p/15039759.html
Copyright © 2020-2023  润新知