[英]Java's flatMap on list of list of optional integers
我有以下一些簡化的代碼無法編譯,我不明白為什么:
List<Optional<Integer>> list =
new ArrayList<>();
List<Integer> flattened =
list
.stream()
.flatMap(i -> i)
.collect(Collectors.toList());
編譯器告訴我:
[ERROR] ... incompatible types: cannot infer type-variable(s) R
[ERROR] (argument mismatch; bad return type in lambda expression
[ERROR] Optional<Integer> cannot be converted to Stream<? extends R>)
[ERROR] where R,T are type-variables:
[ERROR] R extends Object declared in method <R>flatMap(Function<? super T,? extends Stream<? extends R>>)
[ERROR] T extends Object declared in interface Stream
我承認我不習慣Java,但我必須參與一個項目。 我在Scala中list.flatten
了這個,其中list.flatten
和等效的list.flatMap(i => i)
正如預期的那樣工作:
val list = List(Some(1), Some(2), None)
list.flatten // List(1, 2)
Java的flatMap
不同的?
它應該是:
List<Integer> flattened =
list
.stream()
.filter (Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
你flatMap
希望是一種把一個函數Stream
元素的Stream
。 您應該使用map
(以提取Optional
的值)。 此外,您需要過濾掉空的Optional
s(除非您希望將它們轉換為null
)。
沒有過濾:
List<Integer> flattened =
list
.stream()
.map(o -> o.orElse(null))
.collect(Collectors.toList());
Java的flatMap是不同的?
flatMap
方法期望提供的函數返回一個流但是i -> i
沒有提供。 在JDK8中,您需要從Optional中創建一個流然后展平:
list.stream()
.flatMap(i -> i.isPresent() ? Stream.of(i.get()) : Stream.empty())
.collect(Collectors.toList());
或者在JDK9中,可以完成如下:
list.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Stream.flatMap(Function<? extends T, ? extends Stream<? extends R>>)
文檔 Stream.flatMap(Function<? extends T, ? extends Stream<? extends R>>)
:
返回一個流,該流包含將此流的每個元素替換為通過將提供的映射函數應用於每個元素而生成的映射流的內容的結果。 在將其內容放入此流后,每個映射的流都將關閉。 (如果映射的流為
null
,則使用空流。)這是一個中間操作。API注意:
flatMap()
操作具有將一對多轉換應用於流的元素,然后將生成的元素展平為新流的效果。
如您所見,該方法用於獲取每個元素,從中創建流 ,然后將每個流展平為單個流(由方法返回)。 這樣做:
List<Optional<Integer>> optionals = ...;
List<Integer> integers = optionals.stream()
.flatMap(optional -> optional) // identity function
.collect(Collectors.toList());
無效,因為函數返回一個Optional
而不是一個Integer
Stream
。 要解決此問題,您需要更改函數以返回Optional
包含的Stream
。 根據您使用的Java版本,您可以執行以下操作:
Java 9+,
List<Optional<Integer>> optionals = ...;
List<Integer> integers = optionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Java 8,
// There are different ways to convert an Optional into a Stream using
// flatMap, this is just one option. Holger shows other ways in the comments.
List<Optional<Integer>> optionals = ...;
List<Integer> integers = optionals.stream()
.flatMap(optional -> optional.isPresent() ? Stream.of(optional.get()) : Stream.empty())
.collect(Collectors.toList());
其他選項包括使用map
結合filter
或Optional
方法。 有關示例,請參閱Eran的答案 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.