Это очень интересный вопрос, однако, не существует выделенного сборщика для обработки такого варианта использования.
Все, что вы можете, это использовать 3 итерации (Streams) соответственно:
List<String> names = employees.stream().map(Emp::name).collect(Collectors.toList());
List<Integer> ids = employees.stream().map(Emp::id).collect(Collectors.toList());
List<Integer> ages = employees.stream().map(Emp::age).collect(Collectors.toList());
Редактировать - написать собственный коллектор : вы можете использовать перегруженный метод Stream::collect(Supplier, BiConsumer, BiConsumer)
, чтобы реализовать свой собственный коллектор, делая то, что вам нужно:
Map<String, List<Object>> newMap = employees.stream().collect(
HashMap::new, // Supplier of the Map
(map, emp) -> { // BiConsumer accumulator
map.compute("names", remappingFunction(emp.getName()));
map.compute("ages", remappingFunction(emp.getAge()));
map.compute("ids", remappingFunction(emp.getId()));
},
(map1, map2) -> {} // BiConsumer combiner
);
Практически все, что он делает, - это извлекает требуемое значение (name
, age
...) и добавляет его к List
под ключом c "names"
, "ages"
et c. используя метод Map::compute
, который позволяет вычислить новое значение на основе существующего (null
по умолчанию, если ключ не использовался).
remappingFunction
, который фактически создает новое List
или добавляет значение, выглядит следующим образом:
private static BiFunction<String, List<Object>, List<Object>> remappingFunction(Object object) {
return (key, list) -> {
if (list == null)
list = new ArrayList<>();
list.add(object);
return list;
};
}