Stream——获取集合中某个字段最前的值

本文详细介绍了如何使用Java 8的Stream API进行数据处理,包括数据集合判空、排序、过滤和获取特定数据。通过Optional避免了空指针异常,并展示了对数据进行排序(升序和降序)的方法。文章提供了实用的代码示例,有助于理解Stream API的高效用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前,针对Stream链式编程中的几个方法做了大致的说明。详情可以参考:

JDK 1.8 新特性之Stream 详解个人笔记

但实际业务中,总会存在很多复杂的思维,需要使用到Stream,此时玩的不熟练总感觉无从下手。

今后开始写几种常用的逻辑方式。

定义数据接收类

因为要考虑使用集合,需要使用到自定义类对象,所以先从定义对象开始。

public class User {
    private String name;
    private BigDecimal age;
    private Integer num;

    public User(String name, BigDecimal age) {
        this.name = name;
        this.age = age;
    }

    public User(String name, BigDecimal age, Integer num) {
        this.name = name;
        this.age = age;
        this.num = num;
    }
	// get/set
	// toString()
}

定义数据集合

自定义数据集合,模拟数据库查询到的数据信息。

List<User> users = Arrays.asList(
                new User("xj1", new BigDecimal(20),3),
                new User("xj2",  new BigDecimal(3),5),
                new User("xj3",  new BigDecimal(30),1),
                new User("xj4",  new BigDecimal(10),4));

数据筛选

这里时模拟数据,采取手动定义,所以数据一定存在

如果数据是从数据库中查询,此时这里的 users 集合 可能为 null

当出现null.stream()时,会出现报错信息!为了保证代码的健壮性,需要对数据信息进行判空。

1、数据集合判空

常见的stream判空有两种。

1.1、Optional.isPresent()

System.out.println("-----> " + Optional.ofNullable(null).isPresent());
System.out.println("-----> " + Optional.ofNullable(new ArrayList<>()).isPresent());

允许结果:

-----> false
-----> true

可以通过Optional.ofNullable(集合别名).isPresent()判断集合是否存在,再通过返回 boolean 判断是否继续向下执行链式编程代码。

1.2、orElse 替换

还有一种方式,是如果存在空对象,则将空对象进行替换操作。如下所示:

public class Test {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(
                new User("xj1", null),
                new User("xj2",  null),
                new User("xj3",  null),
                new User("xj4",  null));

        System.out.println(Optional.ofNullable(users).orElse(new ArrayList<>()));
        System.out.println(Optional.ofNullable(null).orElse(new ArrayList<>()));
    }
}

在这里插入图片描述
Optional.ofNullable判断指定对象为null时,则会执行orElse(new ArrayList<>())进行替换,避免出现null.stream()NPE问题。

2、排序 sorted

当将指定的集合转化为stream 流后,此时就需要针对数据流进行排序操作。可以采取sorted实现。

List<User> users = Arrays.asList(
        new User("xj1", new BigDecimal(20),3),
        new User("xj2",  new BigDecimal(3),5),
        new User("xj3",  null,1),
        new User("xj4",  new BigDecimal(10),4));

Optional.ofNullable(users)
        .orElse(new ArrayList<User>())
        .stream()
        .sorted(Comparator.comparing(User::getNum)) // 根据编号从小到大排序(默认)
        .forEach(e-> System.out.println(e)); // 只是为了打印流

在这里插入图片描述

3、数据过滤 filter

既然需要获取到指定的字段数据信息,如果明确要求不取为null的数据,此时则需要排序后的集合数据流进行数据的过滤,排除数据字段为null的数据信息。

List<User> users = Arrays.asList(
                new User("xj1", new BigDecimal(20),3),
                new User("xj2",  new BigDecimal(3),5),
                new User("xj3",  null,1),
                new User("xj4",  new BigDecimal(10),4));
                
Optional.ofNullable(users)
                .orElse(new ArrayList<User>())
                .stream()
                .sorted(Comparator.comparing(User::getNum))
                .filter(x->x.getAge()!=null)
                .forEach(e-> System.out.println(e)); // 只是为了打印流

在这里插入图片描述

4、获取第一个数据 findFirst().get()

通常来说,直接采取.findFirst().get(),一般是获取到集合中的 元 对象信息,如下所示:

List<User> users = Arrays.asList(
                new User("xj1", new BigDecimal(20),3),
                new User("xj2",  new BigDecimal(3),5),
                new User("xj3",  null,1),
                new User("xj4",  new BigDecimal(10),4));
                
Optional.ofNullable(users)
                .orElse(new ArrayList<User>())
                .stream()
                .sorted(Comparator.comparing(User::getNum))
                .filter(x->x.getAge()!=null)
                //.forEach(e-> System.out.println(e)); // 只是为了打印流
                .findFirst().get();
System.out.println(user);

在这里插入图片描述
如果数据类对象元素很多,只是想单单获取其中的某个列的值,则可以多加一个map进行映射。

获取指定元对象指定属性值。

List<User> users = Arrays.asList(
                new User("xj1", new BigDecimal(20),3),
                new User("xj2",  new BigDecimal(3),5),
                new User("xj3",  null,1),
                new User("xj4",  new BigDecimal(10),4));
BigDecimal bigDecimal = Optional.ofNullable(users)
                .orElse(new ArrayList<User>())
                .stream()
                .sorted(Comparator.comparing(User::getNum))
                .filter(x -> x.getAge() != null)
                //.forEach(e-> System.out.println(e)); // 只是为了打印流
                .map(User::getAge)
                .findFirst()
                .get();
System.out.println(bigDecimal);

在这里插入图片描述

你以为这样就结束了?

你以为这样就结束了吗?接下来看一个极限栗子:

当你需要获取的列数据全是null,他会返回null吗?

List<User> users = Arrays.asList(
                new User("xj1", null,3),
                new User("xj2",  null,5),
                new User("xj3",  null,1),
                new User("xj4",  null,4));
BigDecimal bigDecimal = Optional.ofNullable(users)
                .orElse(new ArrayList<User>())
                .stream()
                .sorted(Comparator.comparing(User::getNum))
                .filter(x -> x.getAge() != null)
                //.forEach(e-> System.out.println(e)); // 只是为了打印流
                .map(User::getAge)
                .findFirst()
                .get();
System.out.println(bigDecimal);

执行一下,你就会发现新大陆:
在这里插入图片描述
解决这个问题,也很简单,把.get()换成.orElse(BigDecimal.ZERO)

List<User> users = Arrays.asList(
                new User("xj1", null,3),
                new User("xj2",  null,5),
                new User("xj3",  null,1),
                new User("xj4",  null,4));
BigDecimal bigDecimal = Optional.ofNullable(users)
                .orElse(new ArrayList<User>())
                .stream()
                .sorted(Comparator.comparing(User::getNum))
                .filter(x -> x.getAge() != null)
                //.forEach(e-> System.out.println(e)); // 只是为了打印流
                .map(User::getAge)
                .findFirst()
                //.get()
                .orElse(BigDecimal.ZERO);
System.out.println(bigDecimal);

在这里插入图片描述

2022.10.14扩展

sort()默认是根据指定的字段进行升序处理,但在实际业务开发中,往往除了升序可能还需要考虑降序操作。

那么降序又该如何操作?

测试的数据集合:

DmLoanRateTendency dmLoanRateTendency1 = new DmLoanRateTendency();
dmLoanRateTendency1.setEtlDate(DateUtil.parseDate("2022-10-14"));

DmLoanRateTendency dmLoanRateTendency2 = new DmLoanRateTendency();
dmLoanRateTendency2.setEtlDate(DateUtil.parseDate("2022-09-14"));

DmLoanRateTendency dmLoanRateTendency3 = new DmLoanRateTendency();
dmLoanRateTendency3.setEtlDate(null);

DmLoanRateTendency dmLoanRateTendency4 = new DmLoanRateTendency();
dmLoanRateTendency4.setEtlDate(DateUtil.parseDate("2022-08-14"));
List<DmLoanRateTendency> dmLoanRateTendencies = Arrays.asList(dmLoanRateTendency1,
        dmLoanRateTendency2, dmLoanRateTendency3,dmLoanRateTendency4);

一般排序输出结果:

Date date = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
        .stream()
        .filter(x->x.getEtlDate()!=null)
        .sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate))
        .map(DmLoanRateTendency::getEtlDate)
        .findFirst().get();
System.out.println(DateUtil.formatDate(date));

2022-08-14

1、使用reversed()排序反转

// sorted 排序中的 Comparator 增加 reversed() 反转,表示降序
        // 方式一:先升序排列,再降序
Date date2 = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
        .stream()
        .filter(x->x.getEtlDate()!=null)
        .sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate)
        	.reversed())
        .map(DmLoanRateTendency::getEtlDate)
        .findFirst().get();
System.out.println(DateUtil.formatDate(date2));

2022-10-14

2、使用Comparator.reverseOrder

// 方式二:Comparator.reverseOrder()
Date date3 = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
        .stream()
        .filter(x->x.getEtlDate()!=null)
        .sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate,
        			Comparator.reverseOrder()))
        .map(DmLoanRateTendency::getEtlDate)
        .findFirst().get();
System.out.println(DateUtil.formatDate(date3));

参考博文

java stream使用指南-------sorted使用及进阶

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值