2017-03-15 76 views
1

我試圖創建下面的類結構的Map<String, List<Moo>> fooMoos;的Java 8流:地圖與子場

值:

class Foo { 
    String id; 
    Bar bar; 
} 

class Bar { 
    List<Moo> moos; 
} 

List<Foo> foos; 

如果穆斯將直接成爲富的一個領域,我會做

Map<String, List<Moo>> fooMoos = foos.stream().collect(Collectors.toMap(Foo::getId, Foo::getMoos)); 

但你怎麼做的subFields?有沒有像Foo :: getBar :: getMoos?

我感覺我需要一個flatMap在這裏,但不知道該怎麼做。

+3

'Collectors.toMap(Foo :: getId,foo - > foo.bar.moos)' – 4castle

+0

我完全忘了,臨時你也可以在那裏使用lambda。謝謝。 – lilalinux

+0

似乎是一種常見模式,忘記了lambda或試圖不惜代價地使用方法引用... – Holger

回答

3

函數引用很有用,但它們不支持鏈接。你需要使用lambda像

foo -> foo.bar.moos 

foo -> foo.getBar().getMoos() 
2

這是簡單得多使用短拉姆達。但是如果你真的想堅持方法引用,可以通過鏈接函數來完成。例如,使用Function.andThen

Map<String, List<Moo>> fooMoos = foos.stream().collect(Collectors.toMap(Foo::getId, 
     ((Function<Foo,Bar>)Foo::getBar).andThen(Bar::getMoos))); 

另外,使用Function.compose

Map<String, List<Moo>> fooMoos = foos.stream().collect(Collectors.toMap(Foo::getId, 
     ((Function<Bar,List<Moo>>)Bar::getMoos).compose(Foo::getBar))); 

與上述類似,在Guava,有一個靜態方法Functions.compose,這將允許您使用泛型類型推斷避免顯式演員表:

Map<String, List<Moo>> fooMoos = foos.stream().collect(Collectors.toMap(Foo::getId, 
     Functions.compose(Bar::getMoos, Foo::getBar))); 
+0

不錯。太糟糕了,只能有一個被接受的答案:-( – lilalinux