在 Java 中流式传输可选的嵌套列表的最有效方法是什么?

What is the most efficient way to stream optional, nested lists in Java?

我一直在这里查看类似的问题,但 none 正在帮助我解决这个特定问题。

我有一个包含列表列表的复杂嵌套对象:

class Container {
    private List<Foo> fooList;
}

class Foo {
    private List<Bar> barList;
}

class Bar {
    private List<Baz> bazList;
}

当我使用 REST api 时,我得到一个 Container 对象,我希望它有一个且只有一个 Baz 实例。到达我的 Baz 对象后,我需要评估谓词。我需要在遍历过程中防止空值。

这是我尝试过的方法:

 Optional.ofNullable(container)
                .map(Container::getFooList)
                .map(List::stream)
                .map(Stream::findFirst)
                .flatMap(Function.identity())
                .map(Foo::getBarList)
                .map(List::stream)
                .map(Stream::findFirst)
                .flatMap(Function.identity())
                .map(Bar::getBazList)
                .map(List::stream)
                .flatMap(Stream::findFirst)
                .map(Baz::getCode)
                .equals(someBaz.getCode());

现在,这可行,但它看起来很糟糕,我认为必须有更好的方法。特别是,调用身份函数似乎是我在 findFirst 调用后可以 flatMap 的唯一方法。

如何更简洁地完成此操作?

我认为一个小的辅助函数可以使这更清楚:

    static <T> Optional<T> getOnlyItem(List<T> ts) {
        if (ts.size() > 1) {
            throw new RuntimeException("Expected singleton list: " + ts);
        }
        return ts.size() == 0 ? Optional.empty() : Optional.of(ts.get(0));
    }

boolean status =
        getOnlyItem(container.getFooList())
                .flatMap(foo -> getOnlyItem(foo.getBarList()))
                .flatMap(bar -> getOnlyItem(bar.getBazList()))
                .map(baz -> baz.getCode())
                .map(code -> code.equals(someBaz.getCode()))
                .orElse(false);

你根本不需要身份函数。 .map(f).flatMap(identity) 等同于 .flatMap(f):

Optional.ofNullable(container)
    .map(Container::getFooList)
    .map(List::stream)
    .flatMap(Stream::findFirst)
    .map(Foo::getBarList)
    .map(List::stream)
    .flatMap(Stream::findFirst)
    .map(Bar::getBazList)
    .map(List::stream)
    .flatMap(Stream::findFirst)
    .map(Baz::getCode)
    .map(x -> x.equals(someBaz.getCode()))
    .orElse(false)

如果它在您的控制范围内,我还建议您将 Container return 变成 Optional<Container>,而不必创建 Optional<Container> ] 内联。

此外,由于 stream 永远不会 return 为空,您可以为每个 getXXXList:

省略一个 map
Optional.ofNullable(container)
    .map(Container::getFooList)
    .flatMap(x -> x.stream().findFirst())
    .map(Foo::getBarList)
    .flatMap(x -> x.stream().findFirst())
    .map(Bar::getBazList)
    .flatMap(x -> x.stream().findFirst())
    .map(Baz::getCode)
    .map(x -> x.equals(someBaz.getCode()))
    .orElse(false)