简体   繁体   English

使用Lambda对列表进行排序和分组

[英]Sorting and the grouping the list using Lambda

lets us suppose I have a Employee list as : 让我们假设我有一个员工列表:

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));
    }

Now what i want is to generate the list which do some filtering like: salary > x and salary < y and sort according to the employee name and then again sort if multiple employee have same name but different salary but now using their salary 现在我想要的是生成一些列表,它执行一些过滤,例如:salary> x和salary <y并根据员工姓名排序,然后再次排序,如果多个员工有相同的名字但工资不同但现在使用他们的工资

what I have done so far is : 到目前为止我所做的是:

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))
        );

for eg: after sorting only name i got:: 例如:排序后只有我得到的名字::

<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>

here are two mike but now Within this two Mike I want to sort their salary in decendeing form so that new result will be: 这里有两个迈克,但现在在这两个迈克我想以分层形式对他们的工资进行排序,以便新的结果将是:

<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>

and except Mike i dont want to change other orders 除了迈克我不想改变其他订单

but i am not able to get the desired result will anyone please help me out what is wrong or what i need to do to further from here. 但我无法得到理想的结果任何人都可以帮助我解决出错的问题或我需要做些什么才能从这里开始。 Thanks :) 谢谢 :)

You are probably looking for 你可能正在寻找

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

If you want to use descending order you can create separate Comparator which will be comparing based on Employee::getSalary and use its reversed() version like: 如果你想使用降序,你可以创建单独的Comparator ,它将基于Employee::getSalary进行comparing ,并使用其Employee::getSalary reversed()版本,如:

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

Possible problem with groupingBy(Employee::getName) is that it returns HashMap which is unordered. groupingBy(Employee::getName)可能问题是它返回无序的HashMap。 If you want to ensure order of keys based on its insertion (and you probably are, otherwise there would be no point in sorting based on name earlier) you could use: 如果你想确保基于其插入的键的顺序(你可能是,否则根据名称排序没有任何意义)你可以使用:

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

Demo: 演示:

//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);
    }
}

Output: 输出:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM