有没有更好的方法来从嵌套的流中获得any值?

String a = obj.getCustomer().getDetails().stream()
    .findAny()
    .map(CustomerDetail::getContact)
    .flatMap(o -> o.getMobiles()
        .stream()
        .findAny()
        .map(o2 -> o2.getNumber()))
    .orElse(null);

这种方法会导致错误--无法将o作为String访问,尽管使用了findAny,但它仍然是Set<String>.

String b = obj.getCustomer().getDetails().stream()
    .findAny()
    .map(CustomerDetail::getContact)
    .map(Contact::getMobiles)
    .stream()
    .findAny()
    .map(o -> o.getNumber()) // ERROR
    .orElse(null);

推荐答案

因此,如果您想要找到任何客户的任何电话号码,第一个代码就可以了.

但是如果你喜欢第二种变体,我可以帮助你.问题是你假设了错误的数据.为了清楚起见,我在代码的每一行都添加了类型:

String b = obj.getCustomer().getDetails().stream() //Stream<CustomerDetail>
    .findAny() //Optional<CustomerDetail>
    .map(CustomerDetail::getContact) //Optional<Contact>
    .map(Contact::getMobiles) //Optional<Set<String>>
    .stream() //Stream<Set<String>> Mistake right here!
    .findAny() //Optional<Set<String>>
    .map(o -> o.getNumber()) // o must be Set<String>!
    .orElse(null);

(我假设您的Java-8标记是错误的,因为您使用了OPTIONAL的stream()-方法,该方法仅在Java 9:https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html#stream()之后才存在)

它所做的基本上是将可选元素转换为一个只有一个(或零个)元素的流,其中只包含可选元素的元素.

要解决此问题,您需要执行以下操作:

String b = obj.getCustomer().getDetails().stream() //Stream<CustomerDetail>
    .findAny() //Optional<CustomerDetail>
    .map(CustomerDetail::getContact) //Optional<Contact>
    .map(Contact::getMobiles) //Optional<Set<String>>
    .stream() //Stream<Set<String>>
    .flatMap(Collection::stream) // Stream<String> new flat map to turn into a Stream of Strings
    .findAny() //Optional<String>
    .map(o -> o.getNumber()) // o is String and compiles
    .orElse(null);

编辑:

基本上,变化所做的就是简单地"解包"集合. 你的代码基本上是一个流,里面只有一个集合.调用Collection::stream将Set转换为Stream(使用从接口Collection继承的stream()-Method).现在,流中将有另一个包含所有移动设备的流.这就是为什么它必须与flatMap而不是map一起使用,后者基本上将第二个流解包到外部流中.这导致现在将一个客户的所有手机都放在流中.

如果你喜欢这个代码是不是更好,现在由你来决定.

Java相关问答推荐

如何让TaskView总是添加特定的列来进行排序?

JsonPath在多个线程中返回错误的值

即使我正在使用并发方法,使用Javascript的应用程序也会继续冻结'

如何在Java中声明未使用的变量?

参数值[...]与预期类型java.util.Date不匹配

在for—each循环中的AnimationTimer中的if语句'

@ IdClass with @ Inheritance(策略= InheritanceType. SINGLE_TABLE)

使用Testcontainers与OpenLiberty Server进行集成测试会抛出SocketException

在Java中,在单个逻辑行中连接列表和单个元素的正确方法是什么?

无法使用Java&;TestContainers获取AWS SQS队列的属性

与不同顺序的组进行匹配,不重复组但分开

如何在代码中将行呈现在矩形前面?

在Java中将int[]矩阵添加到ArrayList中,但出现错误

由于在生成器模式中使用泛型,lambda表达式中的返回类型错误

Dijkstra搜索算法的实现

如何在列表(链表)中插入一个新 node (作为prelast)

在使用具有不同成本的谓词调用allMatch之前对Java流进行排序会带来什么好处吗?

对角线填充二维数组

当使用不同的参数类型调用时,为什么围绕Objects.equals的类型安全包装不会失败?

我们可以在方法中声明接口吗?