在上一讲中, 我们着重的讲了表达式的一些基础知识和基本的使用, 今天我们来实战一把, 对Map的Value值排序进行简化.

在以前的思路我们的做法如下:

  /**
*
* Map根据value排序;
*
* @param map
* @return
*/
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o2.getValue()).compareTo(o1.getValue());
}
}); Map<K, V> result = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}

什么意思呢?意思就是先把Map变成可排序的List使用Comparator接口对entry进行排序, 可是这样代码很多很乱, 我们需要做一些简化.

第一步: 使用Lambda表达式先对Comparator接口做简化, 代码会变成如下情况:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort(Comparator.comparing(Entry::getValue)); Map<K, V> result = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}

 这样的话, 一行代码就代替了五行, 但是会有个问题, 这样写只能从小到大排序很不灵活, 我们还有其他办法.来看下面的代码:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort((o1, o2)-> o2.getValue().compareTo(o1.getValue())); Map<K, V> result = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}

  用lambda表达式就可以做到变换排序的方式, 只要改变o1和o2的顺序就可以了.哎, 可以还是很长, 我还想再少几句代码, 怎么办?

  我们来分析下最原始的排序代码 ---> 首先是将Map转化为List<Entry>利用List的可排序的特性排序后遍历到新的Map里面去, 这样就很简单了, 我们可以从遍历的地方入手.代码如下:

 public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort((o1, o2)-> o2.getValue().compareTo(o1.getValue())); Map<K, V> result = new LinkedHashMap<>();
list.stream().forEach(entry -> result.put(entry.getKey(), entry.getValue())); return result;
}

  也许做到上面这一步已经很满足了, 可是作为一个优秀的开发人员怎么能满足于这种程度, 我们要用两句话完成上面的功能.我们可以发现entrySet()是个集合, stream是有sort方法的, 可以set变成stream然后sort之后forEach到新的Map中, 牛逼吧, 废话少说,看代码.

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
Map<K, V> sortMap = new LinkedHashMap<>();
new map.entrySet().stream()
.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()))
.forEach(entry -> sortMap.put(entry.getKey(), entry.getValue()));
return sortMap;
}

 高级程序员到这里就可以了, 下面提供一个工具类给大家使用.

    /**
* flag = 1 正序
* flag = 0 倒序
* @param map
* @param flag
* @return
*/
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, int flag) {
Map<K, V> sortMap = new LinkedHashMap<>();
if(flag == 1) {
map.entrySet().stream()
.sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue()))
.forEach(entry -> sortMap.put(entry.getKey(), entry.getValue()));
} else {
map.entrySet().stream()
.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()))
.forEach(entry -> sortMap.put(entry.getKey(), entry.getValue()));
}
return sortMap;
}

以上的代码已经够简洁了, 但是有一个中间变量, 我作为一个究极程序员是看不惯的, 能不能把它也省略掉一句代码实现整个功能呢? 答案是可以的.

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue2(Map<K, V> map, int flag) {

        if(flag == 1) {
return map.entrySet().stream().sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).map(entry -> {
Map<K, V> result = new LinkedHashMap<>();
result.put(entry.getKey(), entry.getValue());
return result;
}).reduce((map1, map2) -> {
map2.entrySet().forEach(entry -> map1.put(entry.getKey(), entry.getValue()));
return map1;
}).get();
} else {
return map.entrySet().stream().sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())).map(entry -> {
Map<K, V> result = new LinkedHashMap<>();
result.put(entry.getKey(), entry.getValue());
return result;
}).reduce((map1, map2) -> {
map2.entrySet().forEach(entry -> map1.put(entry.getKey(), entry.getValue()));
return map1;
}).get(); }

思路是做好排序后将排序后的entry加入到新的Map里面, 再将stream<Map<K,V>>进行叠加, 可能有些抽象, 不能明白的也只能帮到这啦.

Java8-2-Lambda表达式实战-一句话实现Map中按照Value排序的更多相关文章

  1. java8的lambda表达式,将List<DTO> 转为 List<DO>

    将List<PhoneDTO>转为List<PhoneDO>,通过java8的lambda表达式来操作,比传统的for循环精简很多: /** * List<PhoneDT ...

  2. java8之lambda表达式(1)-基本语法

    lambda表达式,即带有参数的表达式,为更清晰地理解lambda表达式,先看如下例子: (1) class Student{ private String name; private Double ...

  3. java8的lambda表达式

    关于java8的lambda表达式 lambda表达式一般用于接口,因为lambda表达式是函数式编程. 1.有且仅有一个抽象方法被称为函数式接口,函数式接口可以显示的被@FunctionalInte ...

  4. Java8 Lambda表达式实战之方法引用(一)

    方法的引用 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用 方法 ...

  5. java8之lambda表达式&方法引用(一)

    本文将简单的介绍一下Lambda表达式和方法引用,这也是Java8的重要更新,Lambda表达式和方法引用最主要的功能是为流(专门负责迭代数据的集合)服务. 什么是lambda表达式 可以把lambd ...

  6. java8之lambda表达式入门

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ privat ...

  7. JAVA8之lambda表达式具体解释,及stream中的lambda使用

    前言: 本人也是学习lambda不久,可能有些地方描写叙述有误,还请大家谅解及指正! lambda表达式具体解释 一.问题 1.什么是lambda表达式? 2.lambda表达式用来干什么的? 3.l ...

  8. 十分钟学会Java8的lambda表达式和Stream API

    01:前言一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏 ...

  9. Java8之lambda表达式

    一.什么是lambda表达式? Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码 ...

随机推荐

  1. Android Studio导出JavaDoc时中文乱码问题解决

    导出过程中,如果出现JavaDoc中文乱码的问题,可以在Other command line arguments栏目添加命令参数:-encoding UTF-8 -charset UTF-8(如果是G ...

  2. Java基础——集合(持续更新中)

    集合框架 Java.util.Collection Collection接口中的共性功能 1,添加 booblean add(Object obj);  往该集合中添加元素,一次添加一个 boolea ...

  3. webpack4升级指南

    webpack4升级指南 鉴于图书项目编译速度极慢的情况(项目里面module太多了,编译慢很正常)且最近需求不多(很少出现的空挡期).所以我觉得搞一波webpack升级,看看有没有帮助.webpac ...

  4. 🧬 C# 神经网络计算库和问题求解

    Andrew Kirillov 著 Conmajia 译 2019 年 1 月 12 日 原文发表于 CodeProject(2006 年 11 月 19 日),已获作者本人授权. 本文介绍了一个用于 ...

  5. asp.net三层架构增删改查

    数据库 use master if exists (select * from sysdatabases where name='bond') drop database bond create da ...

  6. SpringBoot从零到上线

    SpringBoot精要 SpringBoot的四个核心 1.自动配置:针对很多Spring应用程序常见的应用功能,SpringBoot能自动提供相关配置. 在任何Spring应用程序的源代码中,都可 ...

  7. Java开发笔记(八十六)通过缓冲区读写文件

    前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...

  8. mysql事件调度器使用

    --设置事件调度器 开启SET GLOBAL event_scheduler = ON; --查看事件调度器 是否开启 on开  off关SHOW VARIABLES LIKE 'event_sche ...

  9. Fundebug支持浏览器报警

    摘要: 除了邮件报警和第三方报警,我们新增了浏览器报警功能. 邮件报警与第三方报警 Fundebug是专业的应用BUG监控服务,当您的线上应用,比如网页.小程序.Java等发生BUG时,我们会第一时间 ...

  10. 二分查找BinarySearch(Java)

    二分查找(折半查找)BinarySearch 二分查找  一组排好顺序的数,查找其中的一个数(value)的位置,按照数组(int[] a)存放这组数据,数组的索引所指的位置就是需要查找的数,用三个变 ...