Java中使用lamda表达式进行foreach,优雅处理集合List为null的情况

Java中使用lamda表达式进行foreach,优雅处理集合List为null的情况

一:举例方法

在使用Java 8及以上版本的Stream API时,如果你想要优雅地处理可能为空的List,可以使用以下方法

1、提前检查

在调用stream之前,先检查list是否为空或null。这是最直接的方法,可以避免调用stream的开销。

List<String> list = null;

if (list != null && !list.isEmpty()) {
    list.stream().forEach(item -> {
        // 处理每一个item
    });
} else {
    // 处理空或null的list
}

2、Optional + Stream

使用Optional来封装可能为null的List,然后使用flatMap将其转换为一个空的Stream或List的Stream。

        Optional.ofNullable(list1)
                // 如果list1非空,应用List::stream方法,如果list为空,map不做任何操作
                .map(List::stream)
                // 如果list1为空,提供一个空的Stream
                .orElseGet(Stream::empty)
                .forEach(item -> {
                    // 处理每一个item
                    System.out.println(item);
                });

这段代码是Java中用于处理可能为空或非空的List对象的方式,旨在以函数式风格避免出现NullPointerException。下面分步解释这段代码的含义:

  1. Optional.ofNullable(list1): 这将list1包装在一个Optional对象中。如果list1null,那么得到的Optional对象将是空的。
  2. .map(List::stream): 这一步尝试将Optional中的list1转换为一个流(Stream)。如果list1是非空的,map操作将会应用传入的lambda表达式或方法引用(这里是List::stream),从而将列表转化为一个流。如果list1是空的,map操作不会做任何事情,Optional仍然为空。
  3. .orElseGet(Stream::empty): 如果前面的Optional是空的(这意味着list1null或者map操作没有执行因为Optional是空的),orElseGet方法会被调用并执行其参数(方法引用Stream::empty),该方法返回一个空的流。因此,无论list1是否为null,这一步都保证了一个流(Stream)会被返回,而不是null
  4. .forEach(item -> { ... }): 这是终端操作,会对前面步骤生成的流中的每个元素执行括号内的代码块。这里的代码块只是打印每个元素的内容。

简单来说,这段代码的作用是,无论list1是否为null或者为空列表,都能安全地对其元素进行遍历操作,而不会引发NullPointerException。如果list1为空或为null,流操作简单地不会执行任何操作,因为它会是一个空的流。

这种方法的好处在于,它不要求先检查list是否为null或空,代码更加简洁,并且在list为null时不会抛出NullPointerException。

3、Collection工具类

如果你可以使用Apache Commons Collections或Guava库,它们提供的工具类可以帮助处理null的情况。

使用Apache Commons Collections:

CollectionUtils.emptyIfNull(list).forEach(item -> {
    // 处理每一个item
});

使用Guava:

Iterables.emptyIfNull(list).forEach(item -> {
    // 处理每一个item
});

这两个方法都会安全地处理null值,如果list为null,它们会返回一个空的集合,这样就可以安全地进行迭代操作而不担心NullPointerException。

二:Optional + Stream和CollectionUtils性能比较

在这两种方式中,第二种方法使用Apache Commons Collections的CollectionUtils.emptyIfNull可能会更高效,原因如下:

  1. 简洁性CollectionUtils.emptyIfNull直接返回原始集合或空集合,不涉及额外的包装和解包步骤。它是一个简单的条件检查,如果输入为null,则返回一个预先定义的空集合。
  2. 性能OptionalmaporElseGet方法会创建更多的对象和函数调用。虽然这种开销在现代JVM上通常很小,但在大量或高频的调用中可能变得显著。
  3. 直观性CollectionUtils.emptyIfNull的表达更加直观,它清晰地表达了操作的目的------如果集合为null,则使用一个空的集合替代。这使得代码的阅读者很容易理解代码的意图。

然而,实际上,性能差异可能是微不足道的,特别是对于小型或中等规模的集合。如果性能是一个关键考虑因素,你应该基于实际的应用场景进行基准测试。很多时候,代码的清晰性和维护性可能比微小的性能差异更为重要。

在现代Java版本中(特别是Java 9及更高),Optional和流的性能得到了大幅优化。因此,如果不是在极端性能敏感的环境下

选择哪个方法更多的是:基于代码风格和可读性的考虑,而不是基于性能

相关推荐
懒大王爱吃狼29 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
秃头佛爷2 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
阿伟*rui2 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
待磨的钝刨2 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck4 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei4 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法