在 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)
我一直在这里查看类似的问题,但 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)