2017-03-31 121 views
1

我試圖使用Stream s從List創建MapJava 8流:使用映射值列表映射到

key應該是原始項目的名稱,

value應該是一些派生的數據。

.map()後的數據流由Integer S和在.collect()的時候,我不能從以前lambda訪問「富」。我如何獲得.toMap()中的原始項目?

這可以用Stream s完成嗎?還是需要.forEach()

(以下代碼僅用於演示,實際代碼當然要複雜得多,我不能使doSomething()Foo的方法)。

import java.util.ArrayList; 
import java.util.Map; 
import java.util.function.Function; 
import java.util.stream.Collectors; 

public class StreamTest { 

    public class Foo { 
     public String getName() { 
      return "FOO"; 
     } 

     public Integer getValue() { 
      return 42; 
     } 
    } 

    public Integer doSomething(Foo foo) { 
     return foo.getValue() + 23; 
    } 

    public Map<String, Integer> run() { 
     return new ArrayList<Foo>().stream().map(foo -> doSomething(foo)).collect(Collectors.toMap(foo.getName, Function.identity())); 
    } 

    public static void main(String[] args) { 
     StreamTest streamTest = new StreamTest(); 
     streamTest.run(); 
    } 
} 

回答

3

在我看來,這並不複雜。我錯過了什麼嗎?

return Stream.of(new Foo()) 
      .collect(Collectors.toMap(Foo::getName, this::doSomething)); 

我非常喜歡方法引用。如果你喜歡->符號,使用

return Stream.of(new Foo()) 
      .collect(Collectors.toMap(foo -> foo.getName(), foo -> doSomething(foo))); 

要麼將​​打破(拋出異常),如果有一個以上的Foo你流的相同名稱。

+0

啊我看,所以轉換不是用.map()完成的,而是在收集階段? – lilalinux

+0

我不確定這是否是唯一的選擇,但我相信這是在這種情況下做收集器內部映射的最簡單的解決方案。 @lilalinux –

+1

花了我幾秒鐘才明白爲什麼'new Foo()'應該是一個數組。如果你想要一個單一的元素流,你可以直接使用'Stream.of(new Foo())'而不會讓讀者感到困惑...... – Holger