在 ifPresent 中收集 lambda
lambda collecting within a ifPresent
如何使用 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());
让我解释一下:
.limit(1)
:将流限制为仅第一个元素(或者 returns 如果初始流为空,则为空流)
.flatMap()
:将流映射为新的流。在这种情况下,返回一个由 Entry#getValue()
中的值组成的新流
.collect(Collectors.toList())
: 最后将值流收集到一个列表中。
正如 Olivier Grégoire 在评论中所说,以下内容也有效:
List result = list.stream()
.limit(1)
.flatMap(info -> info.getMap().stream())
.filter( entry -> entry.getKey().equals("test"))
.map(entry::getValue)
.collect(Collectors.toList());
在我看来,哪个更易读,更清楚地表明了意图。
看起来你有一个包含零个或多个 Info
的 List<Info>
,其中 Info
是某个具有 getMap()
方法的对象 return输入一个 Map<String, Something>
,你想以一个 List<Something>
结束,这是第一个列表项的映射的所有值,它们具有键测试。
您想 map
可选而不是使用 ifPresent
。 ifPresent
是一个终端操作,它不 return 任何东西(只是执行代码)。
list // List<Info>
.stream() // Stream<Info>
.findFirst() // Optional<Info>
.map(info -> info.getMap().entrySet() // Set<Entry<String, Something>>
.stream() // Stream<Entry<String, Something>>
.filter(entry -> entry.getKey().equals("test"))
.map(Entry::getValue) // Stream<Something>
.collect(toList()) // List<Something>
) // Optional<List<Something>>
.orElse(Collections::emptyList) // List<Something>
如果没有指定最后一行,那么您将得到 Optional<List<Info>>
返回。
编辑:Lino 对 limit
的回答更为惯用,除非您真的想以这种方式使用 Optional
,否则请选择那个。
编辑 2:
假设您上面的代码是完整的业务逻辑,您可能只是在列表的第一项中找到 "test" 的值(感谢 Lino limit
)。那将是:
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>
为了完整起见,如果您想在列表中的地图中查找 "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>
假设 info.getMap
returns a java.util.Map
,我根本不明白你为什么需要内部流管道。
只需使用get("test")
获取"test"
键的值:
List result =
list.stream()
.map(info -> info.getMap().get("test"))
.filter(Objects::nonNull)
.limit(1)
.collect(Collectors.toList());
P.S.,不要使用原始类型。您应该将返回列表的类型更改为 List<ValueType>
,其中 ValueType
是 info.getMap()
Map
.
中值的类型
如何使用 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());
让我解释一下:
.limit(1)
:将流限制为仅第一个元素(或者 returns 如果初始流为空,则为空流)
.flatMap()
:将流映射为新的流。在这种情况下,返回一个由 Entry#getValue()
中的值组成的新流
.collect(Collectors.toList())
: 最后将值流收集到一个列表中。
正如 Olivier Grégoire 在评论中所说,以下内容也有效:
List result = list.stream()
.limit(1)
.flatMap(info -> info.getMap().stream())
.filter( entry -> entry.getKey().equals("test"))
.map(entry::getValue)
.collect(Collectors.toList());
在我看来,哪个更易读,更清楚地表明了意图。
看起来你有一个包含零个或多个 Info
的 List<Info>
,其中 Info
是某个具有 getMap()
方法的对象 return输入一个 Map<String, Something>
,你想以一个 List<Something>
结束,这是第一个列表项的映射的所有值,它们具有键测试。
您想 map
可选而不是使用 ifPresent
。 ifPresent
是一个终端操作,它不 return 任何东西(只是执行代码)。
list // List<Info>
.stream() // Stream<Info>
.findFirst() // Optional<Info>
.map(info -> info.getMap().entrySet() // Set<Entry<String, Something>>
.stream() // Stream<Entry<String, Something>>
.filter(entry -> entry.getKey().equals("test"))
.map(Entry::getValue) // Stream<Something>
.collect(toList()) // List<Something>
) // Optional<List<Something>>
.orElse(Collections::emptyList) // List<Something>
如果没有指定最后一行,那么您将得到 Optional<List<Info>>
返回。
编辑:Lino 对 limit
的回答更为惯用,除非您真的想以这种方式使用 Optional
,否则请选择那个。
编辑 2:
假设您上面的代码是完整的业务逻辑,您可能只是在列表的第一项中找到 "test" 的值(感谢 Lino limit
)。那将是:
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>
为了完整起见,如果您想在列表中的地图中查找 "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>
假设 info.getMap
returns a java.util.Map
,我根本不明白你为什么需要内部流管道。
只需使用get("test")
获取"test"
键的值:
List result =
list.stream()
.map(info -> info.getMap().get("test"))
.filter(Objects::nonNull)
.limit(1)
.collect(Collectors.toList());
P.S.,不要使用原始类型。您应该将返回列表的类型更改为 List<ValueType>
,其中 ValueType
是 info.getMap()
Map
.