在上一讲中, 我们着重的讲了表达式的一些基础知识和基本的使用, 今天我们来实战一把, 对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. Cocos Creator—优化首页打开速度

    Cocos Creator是一个优秀的游戏引擎开发工具,很多地方都针对H5游戏做了专门的优化,这是我比较喜欢Cocos Creator的一点原因. 其中一个优化点是首页的加载速度,开发组为了加快首页的 ...

  2. 关于:未能加载文件或程序集“ICSharpCode.SharpZipLib”或它的某一个依赖项异常的解决方案

    问题: 今天项目迁移忽然又个ICSharpCode.SharpZipLib.dll 程序包丢失了,于是我在网上下载一个这样的包,结果程序运行就提示:未能加载文件或程序集“ICSharpCode.Sha ...

  3. 中国IT史上两大严重事故对我们的警醒及预防措施

    20190121 一,历史回顾:20150528携程运维大事故 2015年5月28日上午11点开始,携程旅行网官方网站突然显示404错误页,App也无法使用,业务彻底中断. 据称是因为乌云网公布了携程 ...

  4. Oracle AWR报告生成和性能分析

    目录 一.AWE报告生成步骤 1.1 工具选择 1.2 自动创建快照 1.3 手工创建快照 1.4 生成AWR报告 二.AWR报告分析 2.1 AWR之DB Time 2.2 AWR之load_pro ...

  5. 前端技术大行其道,再不拥抱TypeScript你就老了!

    本篇文章旨在介绍下TypeScript这门新兴的程序设计语言,不需要你有多么强的专业知识,只需要你有半支烟的功夫. 好了,废话不多说,赶紧进入正题.为什么你需要拥抱TypeScript?那么你首先需要 ...

  6. decorator(修饰器)的业务应用

    decrator(修饰器)的业务应用 ES6问世的时间也不短了,而且很多时候对ES6所谓的"熟练应用"基本还停留在下面的几种api应用: const/let 箭头函数 Promis ...

  7. Jenkins高级用法 - Pipeline 安装

    一.总体介绍 总体介绍内容摘自 玩转Jenkins Pipeline(大宝鱼) 1.核心概念 Pipeline,简而言之,就是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的 ...

  8. ASP.NET Core中使用GraphQL - 第二章 中间件

    前文:ASP.NET Core中使用GraphQL - 第一章 Hello World 中间件 如果你熟悉ASP.NET Core的中间件,你可能会注意到之前的博客中我们已经使用了一个中间件, app ...

  9. offset系列,client系列,scroll系列回顾

    一 scroll系列属性      ——滚动

  10. 『集群』007 如何测试Slithice源代码

    如何测试Slithice源代码 直接测试 >你可以直接 进入 “集合编译区”,这里面 已经有 编译好的 所有程序集: >部署 配置数据库: >附加 集合编译区 中的 SQLServe ...