在 Java(8)开发 中,Stream API 提供了一种处理集合的强大方式,但在处理包含空值的流时,可能会遇到一些意想不到的问题。本文将通过一个简单的 User
实体类来演示如何处理空值,并讨论在实际开发中可能遇到的空指针异常(NullPointerException)。
1. 创建 User 实体类
首先,我们定义一个简单的 User
实体类,包含 name
、age
和 country
属性用于演示问题:
@Data
public class User {private String name;private Integer age;private String country;
}
Stream<User> containsNullStream = Stream.of(new User("周润发", 18, "中国"), new User("亚索", 30, "小日子"), new User("贾冰", 49, "中国"), new User("周润发", 18, "中国"), null, null);log.info("nullStream的数量是:{}",containsNullStream.count());
通过数量检查是否元素全部添加进了流
运行结果
nullStream的数量是:6
修改代码,试图访问null对象的getName方法
Stream<User> containsNullStream = Stream.of(new User("周润发", 18, "中国"), new User("亚索", 30, "小日子"), new User("贾冰", 49, "中国"), new User("周润发", 18, "中国"), null, null);containsNullStream.forEach(element -> log.info("element:{}", element.getName()));
由于我们访问了null值的属性,必定会导致空指针异常,如果我这么写,应该都能看出看来
Exception in thread "main" java.lang.NullPointerException
由以上可知,重复的null也是可以被Stream流逐一顺序存储。
为什么会这样?难道有人会这么写?还真有
在实际开发中,类似的情况是常见的。考虑以下代码段,从 Redis 缓存中获取对象并封装到集合中:
@Override
public CodeInfoCache fetchByCode(String code) {if (StrUtil.isBlank(code))return null;Object cachedObj = CustomRedisUtil.getRedisClient().opsForHash().get(RedisKeyConstant.CODE_CACHE_KEY, code);if (cachedObj != null)return fetchById(Long.valueOf(String.valueOf(cachedObj)));Code codeEntity = codeService.getOne(new QueryWrapper<Code>().eq(Code.CODE_FIELD, code));if (codeEntity == null)return null;return this.refreshSingleCache(codeEntity);
}
menuCodes.stream().map(code -> codeService.fetchByCode(code)) .forEach(codeInfoCache -> {// 在这里访问 codeInfoCache的成员方法});
在这里,如果 fetchByCode
方法返回 null
,则在 forEach
中访问 codeInfoCache
的属性时将抛出空指针异常。这种情况在处理大量数据时尤其容易发生,可能导致整个逻辑失败。
5. 解决方案
为了避免空指针异常,可以在访问属性之前进行空值检查。可以使用 Optional
类来处理可能的 null
值,或者在 forEach
中添加条件判断:
menuCodes.stream().map(code -> codeService.fetchByCode(code)).filter(Objects::nonNull) // 过滤掉 null 值.forEach(codeInfoCache -> {// 安全访问 codeInfoCache 的成员方法log.info("Code Info: {}", codeInfoCache.getSomeProperty());});