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操作分组、过滤、求和、最值、排序、去重相关推荐

  1. Java 8 Lambda 表达式Stream操作

    在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流.并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容. 优点: Stream API可以极大提高J ...

  2. 10个Java 8 Lambda表达式经典示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表 达式,它将允许我们将行为传到函数里.在J ...

  3. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  4. Java中Lambda表达式的使用

    目录 1 简介 2  Lambda表达式的组成 2.1  Lambda表达式的函数式接口 2.2 对接口的要求 3 Lambda使用 3.1 基本使用 3.2 使用Lambdas和Streams 4 ...

  5. Java 8 Lambda 表达式详解

    版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某 ...

  6. 设计模式的Java 8 Lambda表达式–命令设计模式

    在本博客中,我将说明如何使用Java 8 Lambda表达式以函数式编程方式实现命令模式 . 命令模式的目的是将请求封装为对象,从而为具有不同请求,队列或日志请求的客户端参数化,并支持相应的操作. 命 ...

  7. Java中Lambda表达式和stream的使用

    Java中Lambda表达式和stream的使用 转自 [*https://www.cnblogs.com/franson-2016/p/5593080.html*] 简介 (译者注:虽然看着很先进, ...

  8. JAVA之Lambda表达式详解

    文章目录 一.基本概念 1.背景 2.Lambda表达式的语法 3.函数式接口 二.Lambda表达式的基本使用 1.无返回值函数式接口 2.有返回值函数接口 3.语法精简 三.变量捕获 1.匿名内部 ...

  9. Java语法—— Lambda表达式

    文章目录 一.基本概念 1.背景 2.Lambda表达式的语法 3.函数式接口 二.Lambda表达式的基本使用 1.无返回值函数式接口 2.有返回值函数接口 3.语法精简 三.变量捕获 1.匿名内部 ...

最新文章

  1. mysql中grade字段降序排列_mysql高级查询
  2. CFCC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries
  3. python微信机器人部署服务器_玩法收藏/云服务器/零基础微信机器人实践( Python )...
  4. Excel 数据批量生成SQL语句
  5. 中国成全球第二AI医疗交易国,上半年AI制药融资数等于去年全年 | 报告
  6. 温故而知新 Ajax 的新坑 dataType: 'json'
  7. web入门--ssti
  8. 分享一个外泌体数据库
  9. 详解Boost电路的基本原理
  10. Algorithms, Part I by Kevin Wayne, Robert Sedgewick
  11. Thinkphp使用CKEditor4富文本编辑器
  12. Misc_PNG高宽详解
  13. git 如何回退单个文件
  14. 解决eWebEditor上传图片提示:请选择一个有效的文件,支持的格式有(GIF|JPG|JPEG|BMP|PNG)!
  15. 正则匹配英文括号( 中文括号【 里面的内容 封装工具类
  16. adf被打开_ADF格式文件 如何打开ADF文件 ADF是什么格式的文件 用什么打开 - The X Online Tools...
  17. 数据分析画图:50道练习玩转matplotlib
  18. 根据百度地图进行IP定位获取地址
  19. Windows计算机与便携式显示器
  20. 支付宝支付回调,回调日志记录

热门文章

  1. 华为云 CentOS 8 下 Nginx 1.20 PHP 8.2 安装
  2. 订购一个月产品,计算多久后到期
  3. 女神结婚了!新垣结衣和星野源宣布结婚曾一起主演《逃避虽可耻但有用》
  4. MySQL之——CentOS6.5_x64安装配置drbd8.4.2
  5. 学C语言找女朋友很难吗?进来看看别人是怎么做的
  6. 从生产到理解分发,第三届“马栏山杯”算法大赛带你了解视频平台AI全流程...
  7. NKN WEB3.0网络峰会精彩片段回顾:特邀嘉宾IPFS/Filecoin
  8. H - Discovering Gold
  9. 轻量级锁、偏向锁、重量级锁详情
  10. 我觉的应该写工作日记了!