使用 Java 8 功能在列表中搜索非空列表

问题描述 投票:0回答:5

我有一个代码片段,我想使其更简洁但更具可读性 使用 Java 8 功能,如 lambdas/streams 等。

基本上,有一个项目列表,每个项目都有一个错误列表。 如果至少有一项至少有一个错误,则需要返回“失败”。如果没有任何错误,则返回“成功”。

Optional<List<Item>> optionalItemList = Optional.ofNullable(message.getItems());

if (optionalItemList.isPresent())
    for (Item item : optionalItemList.get()) {
        Optional<List<Error>> optionalErrorList = Optional.ofNullable((item.getErrors()));
        if(optionalErrorList.isPresent())
            if (!optionalErrorList.get().isEmpty()) {
                return "failure";
            }
        }
        return "success";
java java-8 java-stream option-type
5个回答
11
投票

Optional
并不是要取代
if
语句,而是用作方法的返回值。所以我认为你最好不要用它来完成这项任务。您可以将三元运算符与
Stream.allMatch
一起使用:

return message.getItems() == null || 
       message.getItems().stream()
              .allMatch(i -> i.getErrors() == null || i.getErrors().isEmpty()) ?
      "success" :
      "failure";

顺便说一句,方法永远不应该返回

null
集合。缺少元素应通过返回空集合来表示。这会让你的代码变得更容易:

return message.getItems().stream().allMatch(i -> i.getErrors().isEmpty()) ?
      "success" :
      "failure";

5
投票

您可以使用

flatMap
在列表中搜索列表。我个人认为
List
应该 never
null
,相反它应该是一个空列表。如果这是一个保证,那么代码可能是这样的:

boolean hasError = message.getItems().stream()
    .flatMap(t -> t.getErrors().stream())
    .findAny()
    .isPresent();
return (hasError ? "success" : "failure");

不然代码会变得有点长:

boolean hasError = Optional.ofNullable(message.getItems()).orElse(List.of()).stream()
    .flatMap(t -> Optional.ofNullable(t.getErrors()).orElse(List.of()).stream())
    .findAny()
    .isPresent();
return (hasError ? "success" : "failure");

请注意,我也可以使用

.count() > 0
代替
.findAny().isPresent()
。但前者的缺点是它会迭代所有错误,而后者如果发现任何错误就会短路。


2
投票

对我来说,你让它变得过于复杂。这是一种更简单的方法。如果没有要返回的项目,请确保您的

getItems()
方法返回一个空列表,以便您可以免除如上所述的额外空检查。这种方法不太容易出错,并且可以生成更具可读性的代码。如果您可以对上面的
getErrors
方法执行相同的操作,则只需省略
filter(Objects::nonNull)
即可,这将进一步简化流处理管道。

String errorPresent = message.getItems().stream()
    .map(Item::getErrors).filter(Objects::nonNull)
    .map(List::size).filter(s -> s > 0)
    .findAny().map(ignored -> "failure")
    .orElse("success");

或者,您可以使用三元运算符来完成此操作。

String errorPresent = message.getItems().stream()
    .map(Item::getErrors)
    .filter(Objects::nonNull)
    .anyMatch(e -> !e.isEmpty()) ? "failure" : "success";

1
投票

您可以使用

anyMatch
作为迭代代码:

Optional<List<Item>> optionalItemList = Optional.ofNullable(message.getItems());
if (optionalItemList.isPresent())
    if (optionalItemList.get().stream()
            .map(item -> Optional.ofNullable((item.getErrors())))
            .filter(Optional::isPresent)
            .anyMatch(optionalErrorList -> !optionalErrorList.get().isEmpty())) {
        return "failure";
    }
return "success";

或者进一步简化为:

return Optional.ofNullable(message.getItems())
        .filter(a -> a.stream()
                .map(item -> Optional.ofNullable((item.getErrors())))
                .filter(Optional::isPresent)
                .anyMatch(optionalErrorList -> !optionalErrorList.get().isEmpty()))
        .map(a -> "failure")
        .orElse("success");

0
投票

例如,如果您有以下关系

class Parent {
   ...

   List<Child> children;

   ...
}

您可以简单地执行以下操作,从

Child
列表中获取所有非空
Parent
(子级)。

List<Child> children = parents.stream()
    .map(Parent::getChildren)
    .filter(CollectionUtils::isNotEmpty) // You can use Apache commons/ Spring framework or your custom util method
    .flatMap(Collection::stream)
    .toList();

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.