如何使用Java 8处理可为空的列表?

时间:2018-12-26 23:09:37

标签: java java-8 java-stream optional

我正在拨打服务电话并尝试处理响应。 响应可能包含一些内容。该列表可能为空。

此外,如果列表不为空或不为空,则 它需要被过滤。 如果过滤没有任何内容或响应列表为空或null,则在代码“ entry”中引用可能为null。

当前,当我尝试在空响应列表上使用stream()时,我正在获得NPE。 我该如何处理这种情况?

@Getter
public class ServiceResponse {  
    List<ResponseEntry> entryList;
}

@Getter
public class ResponseEntry {
    String value;
}


ServiceResponse serviceResponse = service.getServiceResponse();
ResponseEntry entry = serviceResponse.getEntryList()
    .stream()
    .filter(e -> "expectedValue".equals(e.getValue()))
    .findFirst()
    .orElse(null);

if (entry == null) { ... }

5 个答案:

答案 0 :(得分:12)

  

如果列表不为空或不为空,则需要对其进行过滤。

这里不需要Optional,因为它不是要替换简单的if检查。

ResponseEntry entry = null;
List<ResponseEntry> responseEntries = serviceResponse.getEntryList();
if(responseEntries != null && !responseEntries.isEmpty()){
    entry = responseEntries.stream()
                .filter(e -> "expectedValue".equals(e.getValue()))
                .findFirst()
                .orElse(null);
}
  • 读取“如果responseEntries不为空并且responseEntries不为空,则应用过滤器操作并找到第一项,否则为空”。可读性强。

另一方面,可选方法:

ResponseEntry entry = Optional.ofNullable(serviceResponse.getEntryList())
                              .orElseGet(() -> Collections.emptyList())
                              .stream()
                              .filter(e -> "expectedValue".equals(e.getValue()))
                              .findFirst();

if(!entry.isPresent()){ ... } // or entry.ifPresent(e -> ...) depending on the logic you're performing inside the block
  • 不必要地创建了可以避免的对象,而实际上并没有意图使用optional来代替简单的“ if”检查。

答案 1 :(得分:7)

在Java 9中,您可以使用新方法Objects.requireNonNullElse(T,T)

Objects.requireNonNullElse(serviceResponse.getEntryList(),
                           Collections.emptyList())

Apache Commons Collections实际上具有方法ListUtils.emptyIfNull(List<T>),如果参数列表为null,则该方法返回一个空列表。甚至更好,但是Objects.requireNonNullElse是Java SE中最接近的东西。

如果您仅限使用Java 8,那么我同意Aomine的回答,即尝试执行Optional之类的事情要比if语句差。

答案 2 :(得分:6)

Stream.ofNullable(Java-9)

  

返回包含 单个元素 如果非空,   否则返回 空流

当前代码

ResponseEntry entry = serviceResponse.getEntryList() // List<ResponseEntry>
        .stream() // NPE here   // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

更新代码

ResponseEntry entry = Stream.ofNullable(serviceResponse.getEntryList()) // Stream<List<ResponseEntry>>
        .flatMap(List::stream) // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter here
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

Optional.stream(Java-9)

  

返回一个顺序的 Stream ,其中仅包含 该值 否则   返回 空流

ResponseEntry entry = Optional.ofNullable(serviceResponse.getEntryList())
        .stream() // Stream<List<ResponseEntry>>
        .flatMap(List::stream) // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter here
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

Optional.isEmpty(Java-11)

  

如果值不存在,则返回 true ,否则返回 false < / em>

Optional<ResponseEntry> entry = Optional.ofNullable(serviceResponse.getEntryList()) // Optional<List<ResponseEntry>>
        .orElseGet(Collections::emptyList) // or else empty List
        .stream() // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter
        .findFirst(); // Optional<ResponseEntry>

if (entry.isEmpty()) { // !entry.isPresent in java-8
   // Do your work here
}

答案 3 :(得分:5)

您可以简单地使用三元运算符:

ServiceResponse serviceResponse = service.getServiceResponse();
List<ResponseEntry> list = serviceResponse.getEntryList();

ResponseEntry entry = (list == null ? Collections.emptyList() : list)
    .stream()
    .filter(e -> "expectedValue".equals(e.getValue()))
    .findFirst()
    .orElse(null);

if (entry == null) { ... }

有时候,传统的IMO更好。

答案 4 :(得分:1)

另一种选择是使用Optional monad

Optional<ResponseEntry> entry = Optional.ofNullable(serviceResponse.getEntryList()).flatMap(list ->
    list.stream().filter(e -> "expectedValue".equals(e.getValue())).findFirst()
);

if (!entry.isPresent()) {
    …
}

如果您的目标是建立(并返回)一个值而不执行副作用,那么甚至可以使用orElseGet而不是该if语句。