java 8 lambda表达式 distinct、groupingBy、filter、forEach、map、sorted、limit、max、anyMatch、allMatch、noneMatch

java8的lambda表达式提供了一些方便list操作的方法,主要涵盖分组、过滤、求和、最值、排序、去重。跟之前的传统写法对比,能少写不少代码。

新建实体类

package com.wh.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class User {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    private Long id;
  
    @ApiModelProperty(value = "员工名称")
    private String name;

    @ApiModelProperty(value = "性别:1->男;2->女;")
    private Integer sex;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "薪资")
    private BigDecimal salary;

    @ApiModelProperty(value = "部门id")
    private Long deptId;

    @ApiModelProperty(value = "状态:1->启用;2->禁用;")
    private Integer state;

    @ApiModelProperty(value = "手机号")
    private String phone;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "创建时间")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "修改时间")
    private LocalDateTime updateTime;
}

初始数据

List<User> userList = new ArrayList<>();

[
{"id":1,"name":"肖战","sex":1,"age":28,"salary":11000.00,"deptId":111,"state":1,"phone":"13800000001","remark":"","createTime":"2022-05-06 17:00:23","updateTime":"2022-05-06 17:00:23"},
{"id":2,"name":"杨紫","sex":2,"age":29,"salary":15000.00,"deptId":222,"state":2,"phone":"13800000002","remark":"","createTime":"2022-05-07 15:10:13","updateTime":"2022-05-07 15:10:13"},
{"id":3,"name":"佩奇","sex":null,"age":28,"salary":20000.00,"deptId":333,"state":1,"phone":"13800000003","remark":"","createTime":"2022-06-06 10:03:10","updateTime":"2022-06-06 10:03:10"},
{"id":4,"name":"易烊千玺","sex":1,"age":30,"salary":30000.00,"deptId":111,"state":1,"phone":"13800000004","remark":"","createTime":"2022-07-26 13:00:43","updateTime":"2022-07-26 13:00:43"},
{"id":1,"name":"肖战","sex":1,"age":28,"salary":11000.00,"deptId":111,"state":1,"phone":"13800000001","remark":"","createTime":"2022-05-06 17:00:23","updateTime":"2022-05-06 17:00:23"}
]

1、去重

// 通过distinct去重
userList = userList.stream().distinct().collect(toList());

2、根据组合去重

// 员工列表根据“姓名;手机号”组合去重
List<User> newUserList = UserList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(r -> r.getName() + ";" + r.getPhone()))), ArrayList::new));

3、分组

通过groupingBy可以分组指定字段

// 根据部门分组
Map<Long, List<User>> userMapByDeptId = userList.stream().collect(Collectors.groupingBy(User::getDeptId));

4、过滤

通过filter方法可以过滤某些条件   

// filter过滤(取所有男员工)
userList = userList.stream().filter(user -> user.getSex() == 1).collect(Collectors.toList());

5、遍历赋值

批量设置列表字段为同一个值。若此时userList为null会报空指针异常java.lang.NullPointerException

// 遍历赋值。
userList.forEach(user -> {
user.setRemark("哈哈");
}); 

6、map取某字段

// 取员工姓名并去重
List<String> userNames = userList.stream().map(User::getName).distinct().collect(Collectors.toList());

// 取启用员工id 
List<Long> sysUserIds = userList.stream().filter(user -> user.getState() == 1).map(user -> user.getId()).collect(Collectors.toList());

7、Collectors.joining(",")将数组转为逗号分隔字符串

String nameStr = userNames.stream().collect(Collectors.joining(","));

8、sorted或sort正序排列

list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。(sort是在原位重新排列列表,而sorted()是产生一个新的列表。)

// sorted按照创建时间正序排列
userList = userList.stream().sorted(Comparator.comparing(User::getCreateTime)).collect(Collectors.toList());
// sort单字段排序,根据id排序
userList.sort(Comparator.comparing(User::getId));
// sort多字段排序,根据id,年龄排序
userList.sort(Comparator.comparing(User::getId).thenComparing(User::getAge));

9、sorted倒叙排列

// 根据创建时间倒叙排序
userList = userList.stream().sorted(Comparator.comparing(User::getCreateTime).reversed()).collect(Collectors.toList());

10、根据条件过滤取第一条数据

// 需求:取手机号为13800000001的第一条数据的名字。
// 取手机号为13800000001的第一条数据,如果不存在则返回null
String name = null;
User user = userList.stream().filter(u -> "13800000001".equals(u.getPhone())).findFirst().orElse(null);
if (user != null){
    name = user.getName();
}

// 也可以通过Optional.isPresent判断是否存在
Optional<User> first = userList.stream().filter(u -> "13800000001".equals(u.getPhone())).findFirst();
if (first.isPresent()) {
    name= first.get().getName();
}

// 过滤后,通过map取名字,如果数据不存在则返回空
name = userList.stream().filter(u -> "13800000001".equals(u.getPhone())).findFirst().map(User::getName).orElse(StringUtils.EMPTY);

11、截取数据

limit作用就是从流中截取maxSize个元素放到新流中返回

// 截取前三名员工
userList = userList.stream().limit(3).collect(Collectors.toList());

12、求和

分基本类型和大数类型求和,基本类型先mapToInt,然后调用sum方法,大数类型使用reduce调用BigDecimal::add方法

//求和
//基本类型
int sumAge = userList.stream().mapToInt(User::getAge).sum();
//BigDecimal求和(需过滤掉bigDecimal对象为null的情况,否则可能会报空指针)
BigDecimal sumSalary = userList.stream().map(User::getSalary).filter(s -> s != null).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal sumSalary = userList.stream().map(User::getSalary).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

判断对象空

stream.filter(x -> x!=null)
stream.filter(Objects::nonNull)

判断字段空

stream.filter(x -> x.getDateTime()!=null)

13、最值

求最小与最大,使用min max方法

// 最大更新时间
LocalDateTime maxUpdateTime = userList.stream().map(User::getUpdateTime).filter(r -> r != null).max(LocalDateTime::compareTo).orElse(null);

// 最大更新时间
LocalDateTime maxUpdateTime = userList.stream().filter(r -> r.getUpdateTime() != null).max(Comparator.comparing(User::getUpdateTime)).map(User::getUpdateTime).orElse(null);

// 最小同理,将.max换成.min

14、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));

15、遍历数组的同时创建另一个数组

List<DeptVO> deptVOList = userList.stream().filter(user -> user.getDeptId == 111L).collect(ArrayList::new, (list, object) -> {
    DeptVO vo = new deptVO();
    vo.setPhone(object.getPhone());
    vo.setSalary(object.getSalary());
    list.add(vo);
}, List::addAll);

// 或者
List<DeptVO> deptVOList = userList.stream().filter(user -> user.getDeptId == 111L).map(user -> {
    DeptVO vo = new deptVO();
    vo.setPhone(user.getPhone());
    vo.setSalary(user.getSalary());
    return vo;
}).collect(Collectors.toList());

16、anyMatch、allMatch、noneMatch

anyMatch只要有一条数据满足条件即返回true;

allMatch必须全部都满足条件才会返回true;

noneMatch全都不满足条件才会返回true。

userList数组中3男一女。

// anyMatch存在一条满足条件的数据,返回true:是否存在性别为男的员工
boolean flag = userList.stream().anyMatch(user -> user.getSex() == 1);
// 返回true;

// allMatch所有数据都满足条件时,返回true:是否所有员工性别都为男
boolean flag = userList.stream().allMatch(user -> user.getSex() == 1);   
// 返回false   

// noneMatch所有数据都不满足条件时,返回true:是否不存在性别为男的员工
boolean flag = userList.stream().noneMatch(user -> user.getSex() == 1); 
// 返回false   

17、对比修改前和修改后的两个数组,查修改后新增及删除的数据。

// 场景:批量修改部门下员工,存在新勾选某个员工,取消勾选某个员工的情况。保存时,需取出本次新增的,和本次删除的。

// userListDB为数据库查出修改前部门下员工,userListParam为前端传过来的修改后部门下的员工

// 本次删除:对比id,取userListDB有,userListParam没有的数据
List<User> userListToDelete = userListDB.stream().filter(db -> userListParam.stream().noneMatch(param -> param.getId().equals(db.getId()))).collect(toList());
// 本次新增:对比id,取userListParam有,userListDB没有的数据
List<User> userListToSave = userListParam.stream().filter(param -> userListDB.stream().noneMatch(db -> db.getId().equals(param.getId()))).collect(toList());
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值