簡體   English   中英

Java的flatMap在可選整數列表的列表中

[英]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結合filterOptional方法。 有關示例,請參閱Eran的答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM