Java 8 Streams:使用子字段中的值进行映射

时间:2017-03-15 21:22:38

标签: java java-8 java-stream

我正在尝试创建Map<String, List<Moo>> fooMoos;

来自以下类结构:

class Foo {
    String id;
    Bar bar;
}

class Bar {
    List<Moo> moos;
}

List<Foo> foos;

如果moos直接成为Foo的一个领域,我会做

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

但是你如何用subFields做到这一点?有没有类似Foo :: getBar :: getMoos?

的东西

我觉得我需要一个flatMap,但不知道该怎么做。

2 个答案:

答案 0 :(得分:3)

函数引用很有用,但它们不支持链接。你需要使用像

这样的lambda
foo -> foo.bar.moos

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

答案 1 :(得分:2)

使用短lambda简单得多。但是如果你真的想坚持方法引用,可以通过链接函数来完成。例如,使用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)));