Java lambda在一个ifPresent中收集

Java lambda在一个ifPresent中收集,java,lambda,java-8,java-stream,collectors,Java,Lambda,Java 8,Java Stream,Collectors,如何使用collect方法在嵌套的ifPresent方法中进行收集 到目前为止,这就是我所拥有的: List result = list.stream() .findFirst() .ifPresent(info -> { info.getMap() .stream() .

如何使用
collect
方法在嵌套的
ifPresent
方法中进行收集

到目前为止,这就是我所拥有的:

List result = list.stream()
                  .findFirst()
                  .ifPresent(info -> {
                      info.getMap()
                          .stream()
                          .filter( entry -> entry.getKey().equals("test"))
                          .map(entry::getValue)
                          .collect(Collectors.toList())                          
                   });

您可能希望这样做:

List result = list.stream()
    .limit(1)
    .flatMap(info -> // <-- removed brace {
        info.getMap().stream()
            .filter( entry -> entry.getKey().equals("test"))
            .map(entry::getValue)
    ) // <-- removed brace here too
    .collect(Collectors.toList());

在我看来,它更具可读性,更清楚地表明了意图。

它看起来像是一个
列表
包含零个或多个
信息
,其中
信息
是一个对象,它有一个
getMap()
方法返回一个
映射
,而您希望最终得到一个
列表
,这是第一个列表项的映射中具有键测试的所有值

您希望
映射
可选项,而不是使用
ifPresent
ifPresent
是一种终端操作,它不返回任何内容(只执行代码)

为了完整性,如果您想在列表中的映射中找到“test”的任何值,应该是:

list.stream() // Stream<List<Info>>
    .flatMap(info::getMap) Stream<Map<String, Something>> 
    .flatMap(map -> map.entrySet().stream()) // Stream<Entry<String, Something>>
    .filter(entry -> entry.getKey().equals("test"))
    .map(Entry::getValue) // Stream<Something>
    .collect(toList()) // List<Something>
list.stream()//流
.flatMap(info::getMap)流
.flatMap(map->map.entrySet().stream())//流
.filter(entry->entry.getKey().equals(“test”))
.map(条目::getValue)//流
.collect(toList())//列表

假设
info.getMap
返回一个
java.util.Map
,我不明白为什么需要内部流管道

只需使用
get(“test”)
获取
测试“
键的值:

List result = 
    list.stream()
        .map(info -> info.getMap().get("test"))
        .filter(Objects::nonNull)
        .limit(1)
        .collect(Collectors.toList()); 

注意,不要使用原始类型。您应该将返回列表的类型更改为
list
,其中
ValueType
info.getMap()中的值类型
Map

为什么它必须是
如果存在
?在这种情况下,为什么不是
flatMap
?或者更确切地说是map()。另外,不要使用原始类型。为什么要在映射的键上过滤它呢?这意味着你在迭代所有元素,而映射的存在就是为了避免这种情况。那么为什么不直接使用
info.getMap().get(“test”)
?类似于
Optional result=list.stream().findFirst().flatMap(info->Optional.ofNullable(info.getMap().get(“test”))--为什么您首先需要一个列表作为结果类型?我在我的答案中添加了第二个编辑,并举例说明OP可能会尝试做什么(基于上述注释)。我认为我们有一套全面的方法来回答他/她目前试图做的任何类型的实现:)在
.map(entry::getValue)
类中
entry
?还是一个变量?这实际上是我从OP的代码中复制的一个打字错误。它应该是
Entry::getValue
(调用
Entry
上的
getValue
方法,调用
entrySet()
时,该iirc是容器类型)。如果您像上面的
过滤器中那样使用
entry->entry.getValue()
,则它将是
entry
。修正我的答案(但同样,Lino的答案更惯用)。我认为你的答案比我的好,我不知道
可选的#map()
甚至存在:)关于OP问题的评论正在挖掘他为什么这样做的原因,呵呵,但我想我们都只是为了正确使用流来回答:)。我更喜欢你的,因为它消除了
列表
可选
(更简洁)之间不必要的转换。我认为你应该调用info.getMap().entrySet().stream(),而不是info.getMap().stream(),来获取流值,对吗?flatMap接受流返回函数。你内心的lambda不会这么做。你应该
.flatmap(info->info.getMap().stream()).filter(…).map(…).collect(…)
@OlivierGrégoire我认为你的版本只是有不同的语义,但总的来说它们是相同的。我更新了答案,也为你指明了方向:)你是对的。对我来说,现在是清晨,我还没有喝咖啡。
list.stream() // Stream<List<Info>>
    .limit(1) // Stream<List<Info>> count 0/1
    .flatMap(info::getMap) Stream<Map<String, Something>> 0/1
    .map(map -> map.get("test")) Stream<Something> 0/1, possibly null
    .filter(Objects::nonNull) Stream<Something> 0/1
    .findFirst() Optional<Something>
list.stream() // Stream<List<Info>>
    .flatMap(info::getMap) Stream<Map<String, Something>> 
    .flatMap(map -> map.entrySet().stream()) // Stream<Entry<String, Something>>
    .filter(entry -> entry.getKey().equals("test"))
    .map(Entry::getValue) // Stream<Something>
    .collect(toList()) // List<Something>
List result = 
    list.stream()
        .map(info -> info.getMap().get("test"))
        .filter(Objects::nonNull)
        .limit(1)
        .collect(Collectors.toList());