java 8 lambda表达式list操作分组、过滤、求和、最值、排序、去重
java8的lambda表达式提供了一些方便list操作的方法,主要涵盖分组、过滤、求和、最值、排序、去重。跟之前的传统写法对比,能少写不少代码。
新建实体类
package com.vvvtimes.vo;import java.math.BigDecimal;
import java.util.Date;public class User {private Long id;//姓名private String name;//年龄private int age;//工号private String jobNumber;//性别private String sex;//入职日期private Date entryDate;//家庭成员数量private BigDecimal familyMemberQuantity;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getJobNumber() {return jobNumber;}public void setJobNumber(String jobNumber) {this.jobNumber = jobNumber;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getEntryDate() {return entryDate;}public void setEntryDate(Date entryDate) {this.entryDate = entryDate;}public BigDecimal getFamilyMemberQuantity() {return familyMemberQuantity;}public void setFamilyMemberQuantity(BigDecimal familyMemberQuantity) {this.familyMemberQuantity = familyMemberQuantity;}
}
1.分组
通过groupingBy可以分组指定字段
//分组Map<String, List<User>> groupBySex = userList.stream().collect(Collectors.groupingBy(User::getSex));//遍历分组for (Map.Entry<String, List<User>> entryUser : groupBySex.entrySet()) {String key = entryUser.getKey();List<User> entryUserList = entryUser.getValue();}
上门的分组存在key空值安全问题,需要做过滤或封装处理
用Optional封装使用中会报No value present
//分组添加累计Map<Optional<Long>, List<SalesOrderMonthlyStatementVo>> groupMap = list.stream().collect(Collectors.groupingBy(x -> Optional.ofNullable(x.getReviewerGroupId())));//遍历分组for (Map.Entry<Optional<Long>, List<SalesOrderMonthlyStatementVo>> entryGroup : groupMap.entrySet()) {Optional<Long> key = entryGroup.getKey();Long groupId = key.get();List<SalesOrderMonthlyStatementVo> entryGroupList = entryGroup.getValue();
}
正确使用方法如下,自定义groupingBy_WithNullKeys
/** Like Collectors.groupingBy, but accepts null keys. */public static <T, A> Collector<T, ?, Map<A, List<T>>>groupingBy_WithNullKeys(Function<? super T, ? extends A> classifier) {return Collectors.toMap(classifier,Collections::singletonList,(List<T> oldList, List<T> newEl) -> {List<T> newList = new ArrayList<>(oldList.size() + 1);newList.addAll(oldList);newList.addAll(newEl);return newList;});}
然后调用
Map<Long, List<SalesOrderMonthlyStatementVo>> groupMap = list.stream().collect(groupingBy_WithNullKeys(x -> x.getReviewerGroupId()));
多字段分组
Function<WarehouseReceiptLineBatch, List<Object>> compositeKey = wlb ->Arrays.<Object>asList(wlb.getWarehouseReceiptLineId(), wlb.getWarehouseAreaId(), wlb.getWarehouseLocationId());Map<Object, List<WarehouseReceiptLineBatch>> map =warehouseReceiptLineBatchList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.toList()));//遍历分组for (Map.Entry<Object, List<WarehouseReceiptLineBatch>> entryUser : map.entrySet()) {List<Object> key = (List<Object>) entryUser.getKey();List<WarehouseReceiptLineBatch> entryUserList = entryUser.getValue();Long warehouseReceiptLineId = (Long) key.get(0);Long warehouseAreaId = (Long) key.get(1);Long warehouseLocationId = (Long) key.get(2);}
2.过滤
通过filter方法可以过滤某些条件
//过滤//排除掉工号为201901的用户List<User> userCommonList = userList.stream().filter(a -> !a.getJobNumber().equals("201901")).collect(Collectors.toList());
3.求和
分基本类型和大数类型求和,基本类型先mapToInt,然后调用sum方法,大数类型使用reduce调用BigDecimal::add方法
//求和//基本类型int sumAge = userList.stream().mapToInt(User::getAge).sum();//BigDecimal求和BigDecimal totalQuantity = userList.stream().map(User::getFamilyMemberQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
上面的求和不能过滤bigDecimal对象为null的情况,可能会报空指针,这种情况,我们可以用filter方法过滤,或者重写求和方法
重写求和方法
package com.vvvtimes.util;import java.math.BigDecimal;public class BigDecimalUtils {public static BigDecimal ifNullSet0(BigDecimal in) {if (in != null) {return in;}return BigDecimal.ZERO;}public static BigDecimal sum(BigDecimal ...in){BigDecimal result = BigDecimal.ZERO;for (int i = 0; i < in.length; i++){result = result.add(ifNullSet0(in[i]));}return result;}
}
使用重写的方法
BigDecimal totalQuantity2 = userList.stream().map(User::getFamilyMemberQuantity).reduce(BigDecimal.ZERO, BigDecimalUtils::sum);
判断对象空
stream.filter(x -> x!=null)
stream.filter(Objects::nonNull)
判断字段空
stream.filter(x -> x.getDateTime()!=null)
4.最值
求最小与最大,使用min max方法
//最小Date minEntryDate = userList.stream().map(User::getEntryDate).min(Date::compareTo).get();//最大Date maxEntryDate = userList.stream().map(User::getEntryDate).max(Date::compareTo).get();
有时候我们需要知道最大最小对应的这个对象,我们可以通过如下方法获取
Comparator<LeasingBusinessContract> comparator = Comparator.comparing(LeasingBusinessContract::getLeaseEndDate);
LeasingBusinessContract maxObject = leasingBusinessContractList.stream().max(comparator).get();
5.List 转map
/*** List -> Map* 需要注意的是:* toMap 如果集合对象有重复的key,会报错Duplicate key ....* user1,user2的id都为1。* 可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2*/Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, a -> a,(k1,k2)->k1));
list转map的时候有时候会将date类型作为key,实际情况中使用string的多,我们可以将某个字段转成string
Map<String, WorkCenterLoadVo> workCenterMap = list.stream().collect(Collectors.toMap(key->DateFormatUtils.format(key.getDate(), "yyyy-MM-dd"), a -> a,(k1,k2)->k1));
list转map有时候会用到多字段key的map结构,除了常用的key用字符串连接,也可以使用apache commons的多字段key形式的map结构MultiKeyMap
6.排序
可通过Sort对单字段多字段排序
//排序//单字段排序,根据id排序userList.sort(Comparator.comparing(User::getId));//多字段排序,根据id,年龄排序userList.sort(Comparator.comparing(User::getId).thenComparing(User::getAge));
实际上这个写法存在空值安全问题,建议改成
userList.sort(Comparator.comparing(User::getId,Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(User::getAge,Comparator.nullsLast(Comparator.naturalOrder())));
7.去重
可通过distinct方法进行去重
//去重List<Long> idList = new ArrayList<Long>();idList.add(1L);idList.add(1L);idList.add(2L);List<Long> distinctIdList = idList.stream().distinct().collect(Collectors.toList());
针对属性去重
List<AddOutboundNoticeDetailsBatchVo> entryDetailsBatchDistinctBatchIdList = entryDetailsBatchList.stream().filter(distinctByKey(b -> b.getMaterialBatchNumberId())).collect(Collectors.toList());//distinctByKey自己定义public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {Map<Object, Boolean> seen = new ConcurrentHashMap<>();return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;}
8.获取list某个字段组装新list
//获取list对象的某个字段组装成新listList<Long> userIdList = userList.stream().map(a -> a.getId()).collect(Collectors.toList());
9.批量设置list列表字段为同一个值
addList.stream().forEach(a -> a.setDelFlag("0"));
10.不同实体的list拷贝
List<TimePeriodDate> timePeriodDateList1 = calendarModelVoList.stream().map(p->{TimePeriodDate e = new TimePeriodDate(); e.setStartDate(p.getBegin());e.setEndDate(p.getEnd()); return e;}).collect(Collectors.toList());
java 8 lambda表达式list操作分组、过滤、求和、最值、排序、去重相关推荐
- Java 8 Lambda 表达式Stream操作
在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流.并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容. 优点: Stream API可以极大提高J ...
- 10个Java 8 Lambda表达式经典示例
Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表 达式,它将允许我们将行为传到函数里.在J ...
- Java 8 Lambda表达式10个示例【存】
PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...
- Java中Lambda表达式的使用
目录 1 简介 2 Lambda表达式的组成 2.1 Lambda表达式的函数式接口 2.2 对接口的要求 3 Lambda使用 3.1 基本使用 3.2 使用Lambdas和Streams 4 ...
- Java 8 Lambda 表达式详解
版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某 ...
- 设计模式的Java 8 Lambda表达式–命令设计模式
在本博客中,我将说明如何使用Java 8 Lambda表达式以函数式编程方式实现命令模式 . 命令模式的目的是将请求封装为对象,从而为具有不同请求,队列或日志请求的客户端参数化,并支持相应的操作. 命 ...
- Java中Lambda表达式和stream的使用
Java中Lambda表达式和stream的使用 转自 [*https://www.cnblogs.com/franson-2016/p/5593080.html*] 简介 (译者注:虽然看着很先进, ...
- JAVA之Lambda表达式详解
文章目录 一.基本概念 1.背景 2.Lambda表达式的语法 3.函数式接口 二.Lambda表达式的基本使用 1.无返回值函数式接口 2.有返回值函数接口 3.语法精简 三.变量捕获 1.匿名内部 ...
- Java语法—— Lambda表达式
文章目录 一.基本概念 1.背景 2.Lambda表达式的语法 3.函数式接口 二.Lambda表达式的基本使用 1.无返回值函数式接口 2.有返回值函数接口 3.语法精简 三.变量捕获 1.匿名内部 ...
最新文章
- mysql中grade字段降序排列_mysql高级查询
- CFCC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries
- python微信机器人部署服务器_玩法收藏/云服务器/零基础微信机器人实践( Python )...
- Excel 数据批量生成SQL语句
- 中国成全球第二AI医疗交易国,上半年AI制药融资数等于去年全年 | 报告
- 温故而知新 Ajax 的新坑 dataType: 'json'
- web入门--ssti
- 分享一个外泌体数据库
- 详解Boost电路的基本原理
- Algorithms, Part I by Kevin Wayne, Robert Sedgewick
- Thinkphp使用CKEditor4富文本编辑器
- Misc_PNG高宽详解
- git 如何回退单个文件
- 解决eWebEditor上传图片提示:请选择一个有效的文件,支持的格式有(GIF|JPG|JPEG|BMP|PNG)!
- 正则匹配英文括号( 中文括号【 里面的内容 封装工具类
- adf被打开_ADF格式文件 如何打开ADF文件 ADF是什么格式的文件 用什么打开 - The X Online Tools...
- 数据分析画图:50道练习玩转matplotlib
- 根据百度地图进行IP定位获取地址
- Windows计算机与便携式显示器
- 支付宝支付回调,回调日志记录
热门文章
- 华为云 CentOS 8 下 Nginx 1.20 PHP 8.2 安装
- 订购一个月产品,计算多久后到期
- 女神结婚了!新垣结衣和星野源宣布结婚曾一起主演《逃避虽可耻但有用》
- MySQL之——CentOS6.5_x64安装配置drbd8.4.2
- 学C语言找女朋友很难吗?进来看看别人是怎么做的
- 从生产到理解分发,第三届“马栏山杯”算法大赛带你了解视频平台AI全流程...
- NKN WEB3.0网络峰会精彩片段回顾:特邀嘉宾IPFS/Filecoin
- H - Discovering Gold
- 轻量级锁、偏向锁、重量级锁详情
- 我觉的应该写工作日记了!