1 场景复现
实体列表,通过stream获取数据,findFirst后,直接使用get获取数据,抛出空指针异常,复现代码如下:
@Test
public void streamGetUnsafeTest() {
List<UserEntity> userEntityList = new ArrayList<>();
userEntityList.add(new UserEntity("1", "111", "male"));
userEntityList.add(new UserEntity("2", "222", "female"));
userEntityList.add(new UserEntity("3", "333", "male"));
userEntityList.add(new UserEntity("4", "444", "female"));
UserEntity userEntity1 = userEntityList.stream().filter(s-> Objects.equals(s.getSex(), "test")).findFirst().get();
}
未查到数据,抛出异常,如图2.1所示。
2 原因
get源码如下,由源码可知,当查不到数据(数据为null)时,get方法直接抛出异常,因此,使用stream获取数据时,需要判断
取到的值是否为null,避免出现空指针。
所在包:package java.util;
类:Optional
/**
* If a value is present in this {@code Optional}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the non-null value held by this {@code Optional}
* @throws NoSuchElementException if there is no value present
*
* @see Optional#isPresent()
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
3 方案
避免通过stream出现空指针异常,主动抛出的,使用orElse给一个预知的默认值,通过默认值处理当前数据。
3.1 安全操作
@Test
public void streamGetSafeTest() {
List<UserEntity> userEntityList = new ArrayList<>();
UserEntity userEntityDefault = new UserEntity();
userEntityList.add(new UserEntity("1", "111", "male"));
userEntityList.add(new UserEntity("2", "222", "female"));
userEntityList.add(new UserEntity("3", "333", "male"));
userEntityList.add(new UserEntity("4", "444", "female"));
UserEntity userEntity1 = userEntityList.stream().filter(s-> Objects.equals(s.getSex(), "test")).findFirst().orElse(userEntityDefault);
logger.info(">>>>>>>>>UserInfo:{}", userEntity1);
}
测试结果如图3.1所示,查到的数据为null时,设置为预知的默认值。
3.2 测试实体
package com.monkey.java_study.common.entity;
/**
* User实体
*
* @author xindaqi
* @since 2021-01-23
*/
public class UserEntity {
/**
* 用户id
*/
private String uid;
/**
* 用户名称
*/
private String nickname;
/**
* 用户性别
*/
private String sex = "haha";
public UserEntity() {
}
public UserEntity(String uid) {
this.uid = uid;
}
public UserEntity(String uid, String nickname, String sex) {
this.uid = uid;
this.nickname = nickname;
this.sex = sex;
}
public UserEntity copy() {
return new UserEntity(uid, nickname, sex);
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "UserEntity{" +
"uid=" + uid +
", nickname='" + nickname + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
4 小结
- 通过stream查询数据时,判断是否会出现空值或者抛出空指针异常;
- 安全的操作是:orElse设定一个预知的默认值。