Группировка API Java 8 Streams по двум полям и возврат обновленной коллекции

У меня есть собственный класс Java, т.е. Сотрудник, имеющий поля ниже,

public class Employee {
     private String name;
     private String dept;
     private Integer age;
     private Double salary;
}

public Employee(String name, String dept, Integer age, Double salary) {
    this.name = name;
    this.dept = dept;
    this.salary = salary;
    this.age = age;
}
//getter and setters

Мой объект списка имеет данные ниже,

List<Employee> list = Arrays.asList(
            new Employee("mahesh", "IT", 25, 1000.00), 
            new Employee("rajesh", "IT", 30, 1200.00), 
            new Employee("Saket", "IT", 30, 1000.00), 
            new Employee("Samuel", "IT", 30, 1150.00), 
            new Employee("Anil", "Eng", 29, 2000.00),
            new Employee("Sachin", "Eng", 29, 2000.00));

Мне нужно перебрать этот список, и обновленный список должен вернуть первую, третью, пятую и шестую записи. сгруппируйте записи, используя отдел и зарплату, и если число группировок больше 1, эти записи должны вернуться. В приведенном выше примере второй и четвертый раз это произошло один раз в виде группировки, поэтому эти записи должны пропускаться.

Итак, окончательный список должен содержать эти записи:

 List<Employee> list = Arrays.asList(
            new Employee("mahesh", "IT", 25, 1000.00), 
            new Employee("Saket", "IT", 30, 1000.00), 
            new Employee("Anil", "Eng", 29, 2000.00),
            new Employee("Sachin", "Eng", 29, 2000.00));

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

«обновленный список должен возвращать первую, третью, пятую и шестую записи» — Почему? Вам нужно кое-что объяснить. Покажите ожидаемый результат и объясните, почему. Голосование за закрытие как неясное. И, скорее всего, дубликат тоже.

Basil Bourque 27.06.2024 08:11

@BasilBourque, потому что у первого и третьего один и тот же отдел, то есть «ИТ», и одинаковая зарплата, то есть 1000,00. Аналогично пятому и шестому, т. е. кафедра «Инж» и зарплата у обоих 2000,00. То, что не ясно?

Abra 27.06.2024 08:34

@Abra Хороший вопрос явно излагает свои требования, а не заставляет меня гадать.

Basil Bourque 27.06.2024 18:01

@BasilBourque Мне не нужно было догадываться.

Abra 27.06.2024 20:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
95
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вы можете попробовать следующий фрагмент кода


 public static void main(String[] args) {
        List<Employee> list = Arrays.asList(
            new Employee("mahesh", "IT", 25, 1000.00), 
            new Employee("rajesh", "IT", 30, 1200.00), 
            new Employee("Saket", "IT", 30, 1000.00), 
            new Employee("Samuel", "IT", 30, 1150.00), 
            new Employee("Anil", "Eng", 29, 2000.00),
            new Employee("Sachin", "Eng", 29, 2000.00)
        );

        
        // Group by concatenated department and salary key
        Map<String, List<Employee>> groupedByDeptAndSalary = filteredList.stream()
            .collect(Collectors.groupingBy(emp -> emp.getDept() + "-" + emp.getSalary()));

        // Flatten the groups and retain only those with more than one element
        List<Employee> result = groupedByDeptAndSalary.values().stream()
            .filter(group -> group.size() > 1)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());

        result.forEach(System.out::println);
    }

В этом решении:

1. сгруппируйте отфильтрованных сотрудников по отделам и зарплатам (составьте их как идентификатор).

2. Выровнять группы и отфильтровать их, чтобы сохранить только те группы, в которых более одного сотрудника.

3.соберите результаты и распечатайте их.

Это должно дать вам желаемый результат:

Employee{name='mahesh', dept='IT', age=25, salary=1000.0}
Employee{name='Saket', dept='IT', age=30, salary=1000.0}
Employee{name='Anil', dept='Eng', age=29, salary=2000.0}
Employee{name='Sachin', dept='Eng', age=29, salary=2000.0}

Насколько я понимаю, критерий 1 представлял собой описание желаемого результата, а не шаг в процессе группировки/фильтрации.

Andrew Yim 27.06.2024 07:14

@AndrewYim, ты прав.

Anil Nivargi 27.06.2024 07:18

о, я понял, я изменю ответ

Peng 27.06.2024 08:57
Ответ принят как подходящий

Если вас интересуют элементы, которые не являются уникальными при группировке по сочетанию отдела и зарплаты, вы можете выполнить группировку и фильтрацию на основе количества. Кроме того, для этого потребуется плоское отображение элементов обратно для структуры данных, желаемой на выходе:

    List<Employee> employees = list.stream()
            .collect(Collectors.groupingBy(employee -> employee.dept + employee.salary))
            .entrySet()
            .stream()
            .filter(e -> e.getValue().size() > 1)
            .flatMap(e -> e.getValue().stream())
            .collect(Collectors.toList());

Примечание. Это зависит от уникальности ключа, созданного с использованием комбинации отдела и зарплаты, представленной типом String.

это сработало, как и ожидалось.

Anil Nivargi 27.06.2024 10:12

Почему люди всегда придумывают ненадежную и неэффективную конкатенацию строк для создания составного ключа? Простое использование функции группировки employee -> Arrays.asList(employee.dept, employee.salary) обеспечивает надежный групповой ключ. Кстати, можно сначала стримить через values() вместо entrySet(), тогда не надо звонить getValue()

Holger 27.06.2024 19:58

Другие вопросы по теме