Как собрать Список <Foo>на Картуиспользуя Java лямбды? - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть объект Foo, который имеет ссылки на Bar и Baz объекты:

public class Foo {
    private Bar bar;
    private Baz baz;

    public Foo(Bar bar, Baz baz) {
       this.bar = bar;
       this.baz = baz;
    }
}

У меня есть List<Foo>, который я хотел бы преобразовать в Map,Мне бы хотелось, чтобы ключ был Bar, а значение было List<Baz>.

. Я могу создать Map, где Bar - это ключ, а значение - List<Foo>:

Map<Bar, List<Foo>> mapBarToFoos = foos.stream().collect(Collectors.groupingBy(Foo::getBar));

Я не знаю, как сделать последний шаг и превратить Список значений в List<Baz>.Есть ли лямбда-преобразование в значение, которое я не вижу?

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Чтобы изменить классический grouping на Map<Bar, List<Foo>>, вам необходимо использовать метод, который позволяет изменять значения карты:

//Use the import to reduce the Collectors. redundancy
//import static java.util.stream.Collectors.*;

Map<Bar, List<Baz>> mapBarToFoos = 
         foos.stream().collect(groupingBy(Foo::getBar, mapping(Foo::getBaz, toList())));

//without you'll get
Map<Bar, List<Baz>> mapBarToFoos = 
         foos.stream().collect(Collectors.groupingBy(Foo::getBar, Collectors.mapping(Foo::getBaz, Collectors.toList())));
0 голосов
/ 12 декабря 2018

Вы близки, вам нужно будет поставить "нисходящий" коллектор для дальнейшего уточнения ваших критериев.в этом случае подход groupingBy вместе с нисходящим коллектором mapping является идиоматическим подходом, т. е.

list.stream().collect(groupingBy(Foo::getBar, mapping(Foo::getBaz, toList())));

. По сути, это работает путем применения нисходящего коллектора mapping к результатам классификации (Foo::getBar) функция.По сути, мы сделали отображение каждого Foo объекта на Baz и поместили его в список.


Просто хотел показать другой вариант здесь, хотя он не так удобен для чтения, как подход groupingBy:

foos.stream()
    .collect(toMap(Foo::getBar, v -> new ArrayList<>(singletonList(v.getBaz())),
            (l, r) -> {l.addAll(r); return l;}));
  • Foo::getBar - это функция keyMapper дляизвлекать ключи карты.
  • v -> new ArrayList<>(singletonList(v)) - это функция valueMapper для извлечения значений карты.
  • (l, r) -> {l.addAll(r); return l;} - это функция слияния, используемая для объединения двух списков, которые имеют одинаковыйgetBar значение.
0 голосов
/ 12 декабря 2018

Я думаю, что вы хотите

list.stream().collect(groupingBy(Foo::getBar, 
    mapping(Foo::getBaz, toList())));

Где getBaz - «нисходящий коллектор», который преобразует сгруппированные Foo s, затем еще один, который создает список.

...