Получение нескольких списков свойств из списка объектов в Java 8 - PullRequest
0 голосов
/ 10 апреля 2020

Учитывая, что у меня есть список объектов List<Emp>, где Emp имеет 3 свойства name, id и age. Какой самый быстрый способ получить 3 списка, таких как List<String> names, List<String> ids и List<Integer> ages.

Самое простое, что я могу придумать, - это перебирать весь список и продолжать добавлять его в эти 3 списка. Но мне было интересно, есть ли более простой способ сделать это с Java 8 потоков?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 10 апреля 2020

Это очень интересный вопрос, однако, не существует выделенного сборщика для обработки такого варианта использования.

Все, что вы можете, это использовать 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;
    };
}
0 голосов
/ 10 апреля 2020

Java 8 Stream имеет некоторый API для разделения списка на разделы, например: 1. Collectros.partitioningBy(..) - который создает два раздела на основе некоторого Predicate и возвращает Map<Boolean, List<>> со значениями; 2. Collectors.groupingBy() - который позволяет группировать поток по некоторому ключу и возвращать полученную Карту.

Но это не совсем ваш случай, так как вы хотите поместить все свойства объекта Emp в разные Lists. Я не уверен, что это может быть достигнуто с помощью такого API, может быть, с некоторыми грязными обходными путями.

Так что, да, самый чистый способ - это перебрать список Emp и вывести все свойства в три Списки вручную, как вы предложили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...