【问题标题】:How to return false for an empty list if using Stream.allMatch()?如果使用 Stream.allMatch(),如何为空列表返回 false?
【发布时间】:2019-03-15 21:21:39
【问题描述】:

我想对 Java 流使用一个语句。

我想过滤所有要求为“真”的服务工作对象,然后检查所有服务工作对象的状态是否为“完成”。

但如果 serviceworkList 为空,则变量“validate”为 false。 我知道 allMatch 的规范,如果列表为空,则返回为真。

关于如何重建流的任何建议,如果列表为空,我会得到错误?

public class Service{

    List<ServiceWork> serviceWorkList = new ArrayList<>();


    boolean validate = serviceWorkList
        .stream()
        .filter(ServiceWork::isRequirement)
        .allMatch(a -> a.getStatus() == Status.DONE);

}

class ServiceWork {

    private Status status;
    private boolean isRequirement;

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public boolean isRequirement() {
        return isRequirement;
    }

    public void setRequirement(boolean requirement) {
        isRequirement = requirement;
    }
}

enum Status {
    DONE, NOT_DONE
}

【问题讨论】:

  • 您的意思是“如果serviceWorkList 为空”还是“如果没有与谓词ServiceWork::isRequirement 匹配的元素”?
  • @Holger:我的意思是如果没有与谓词匹配的元素
  • serviceWorkList .stream() .filter(ServiceWork::isRequirement) .map(a -&gt; a.getStatus() == Status.DONE) .reduce(Boolean::logicalAnd) .orElse(false);
  • 看起来像 stackoverflow.com/questions/46075776 的副本

标签: java java-stream


【解决方案1】:

只需添加一个额外的检查列表是否为空:

boolean validate = !serviceWorkList.isEmpty() && serviceWorkList
    .stream()
    .filter(ServiceWork::isRequirement)
    .allMatch(a -> a.getStatus() == Status.DONE);

在你的评论之后,你可以使用这个:

Set<Status> status = serviceWorkList
    .stream()
    .filter(ServiceWork::isRequirement)
    .map(ServiceWork::getStatus())
    .collect(Collectors.toCollection(() -> EnumSet.noneOf(Status.class)));

boolean validate = status.remove(Status.DONE) == Status.DONE && status.isEmpty();

它首先将所有状态收集到一个EnumSet,然后从集合中删除Status.DONE,如果集合为空,则每个元素都有getStatus() == Status.DONE

这消除了短路,因此即使遇到Status 而不是Status.DONE,它仍然会遍历serviceWorkerList

【讨论】:

  • 我的意思是如果没有匹配谓词 ServiceWork::isRequirement 的元素
【解决方案2】:

Stream.allMatch() 对于空列表将始终返回 true

您应该添加其他验证,例如

boolean validate = !serviceWorkList.isEmpty() && serviceWorkList
    .stream()
    .filter(ServiceWork::isRequirement)
    .allMatch(a -> a.getStatus() == Status.DONE);

【讨论】:

  • 我的意思是如果没有匹配谓词 ServiceWork::isRequirement 的元素
【解决方案3】:

在一个流操作中完成整个验证是不切实际的。我建议两个流操作:

    boolean allRequirementsDone = serviceWorkList.stream()
            .filter(ServiceWork::isRequirement)
            .allMatch(a -> a.getStatus() == Status.DONE);
    boolean atLeastOneRequirement = serviceWorkList.stream()
            .anyMatch(ServiceWork::isRequirement);
    boolean validate = allRequirementsDone && atLeastOneRequirement;

【讨论】:

    猜你喜欢
    • 2015-07-25
    • 1970-01-01
    • 2020-04-07
    • 2015-05-14
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 2021-02-26
    • 2018-08-26
    相关资源
    最近更新 更多