2017-03-31 108 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