2016-01-30 4 views
3

позволяет нам предположить, у меня есть список Employee как:Сортировка и группировка списка с помощью лямбда-

private static List<Employee> list = new ArrayList<Employee>(); 
    static { 
     list.add(new Employee("Joe", 100000, 1980)); 
     list.add(new Employee("Tim", 50000, 1982)); 
     list.add(new Employee("Mike", 90000, 1970)); 
     list.add(new Employee("Rick", 50000, 1955)); 
     list.add(new Employee("Andy", 60000, 1966)); 
     list.add(new Employee("Tim", 10000, 1995)); 
     list.add(new Employee("Tony", 130000, 1991)); 
     list.add(new Employee("Timmy", 150000, 1988)); 
     list.add(new Employee("Rich", 50000, 1980)); 
     list.add(new Employee("Andrew", 160000, 1970)); 
     list.add(new Employee("Ton", 150000, 1958)); 
     list.add(new Employee("Jose", 40000, 1970)); 
     list.add(new Employee("Timothy", 50000, 1996)); 
     list.add(new Employee("Ricardo", 50000, 1988)); 
     list.add(new Employee("Gemasio", 60000, 1971)); 
     list.add(new Employee("Mike", 80000, 1992)); 
    } 

Теперь то, что я хочу, чтобы создать список, который делают некоторую фильтрацию как: зарплата> х и зарплата < у и сортировать по имени сотрудника, а затем снова сортировать, если несколько работник имеют одинаковое имя, но разные зарплаты, но теперь используют их зарплаты

, что я сделал до сих пор:

System.out.println(
       list.stream() 
        .filter(e -> e.getSalary() > 55000) 
        .filter(e -> e.getSalary() < 120000) 
        .sorted(Comparator.comparing(Employee::getName)) 
        .collect(Collectors.groupingBy(Employee::getName)) 
     ); 

для например: после сортировки только имени я получил ::

<name: Andy salary: 60000 year of birth: 1966>, 
    <name: Gemasio salary: 60000 year of birth: 1971>, 
    <name: Joe salary: 100000 year of birth: 1980>, 
    <name: Mike salary: 90000 year of birth: 1970>, 
    <name: Mike salary: 80000 year of birth: 1992> 

здесь два микрофона, но теперь в течение этого два Майка я хочу, чтобы отсортировать их зарплату в decendeing формы, так что новый результат будет:

<name: Andy salary: 60000 year of birth: 1966>, 
    <name: Gemasio salary: 60000 year of birth: 1971>, 
    <name: Joe salary: 100000 year of birth: 1980>, 
    <name: Mike salary: 80000 year of birth: 1970>, 
    <name: Mike salary: 90000 year of birth: 1992> 

и, кроме Майка я не хочу, чтобы изменить другие заказы

, но я не могу получить желаемый результат будет кто-нибудь пожалуйста, помогите мне, что не так и что мне нужно сделать, чтобы Furt ее отсюда. Спасибо :)

+1

Возможно ли иметь два Майка с одинаковой зарплатой (и позволяет говорить с разным годом рождения)? Если да, как вы хотите с ними справиться? – Pshemo

+0

да два сотрудника могут иметь одно и то же имя и одинаковые зарплаты с разными добами, его можно управлять с помощью hashcode() –

ответ

5

Вы, вероятно, ищете

.sorted(Comparator 
     .comparing(Employee::getName)   //sort by name 
     .thenComparing(Employee::getSalary)) //in case of same names sort by salary 

Если вы хотите использовать убывающий порядок вы можете создать отдельный Comparator который будет comparing на основе Employee::getSalary и использовать его версию reversed() как:

 .sorted(Comparator 
       .comparing(Employee::getName) 
       .thenComparing(
         Comparator.comparing(Employee::getSalary).reversed() 
       ) 
     ) 

Возможная проблема с groupingBy(Employee::getName) в том, что она возвращает HashMap, который неупорядочен. Если вы хотите, чтобы обеспечить порядок ключей на основе его включения (и вы, вероятно, в противном случае не было бы никакого смысла сортировки на основе имени ранее), вы можете использовать:

.collect(Collectors.groupingBy(Employee::getName, LinkedHashMap::new, Collectors.toList())); 

Демо:

//code creating list 
//... 

//our code 
Map<String, List<Employee>> grouped = list.stream() 
     .filter(e -> e.getSalary() > 55000) 
     .filter(e -> e.getSalary() < 120000) 
     .sorted(Comparator 
       .comparing(Employee::getName) 
       .thenComparing(
         Comparator.comparing(Employee::getSalary).reversed() 
       ) 
     ) 
     .collect(Collectors.groupingBy(Employee::getName, LinkedHashMap::new, Collectors.toList())); 

for (Map.Entry<String, List<Employee>> entry : grouped.entrySet()) { 
    System.out.println(entry.getKey()); 
    for (Employee emp : entry.getValue()) { 
     System.out.println("\t" + emp); 
    } 
} 

Выход:

Andy 
    Employee [name=Andy, salary=60000, yearOfBirth=1966] 
Gemasio 
    Employee [name=Gemasio, salary=60000, yearOfBirth=1971] 
Joe 
    Employee [name=Joe, salary=100000, yearOfBirth=1980] 
Mike 
    Employee [name=Mike, salary=90000, yearOfBirth=1970] 
    Employee [name=Mike, salary=80000, yearOfBirth=1992] 
+0

. Кроме того, вы можете сгруппировать в «TreeMap» и пропустить шаг сортировки ... – Holger

+0

@ Holger True, по крайней мере, мы могли бы пропустить явное сортирование по имени, поскольку TreeMap может использовать естественный порядок ключа. Но нам все равно придется сортировать значения в списке. Раньше я думал о том, чтобы добавить это к ответу, но решил оставить других в качестве отдельного решения (так что не стесняйтесь делать это) – Pshemo

Смежные вопросы