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

3

假设我有一个员工列表:

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

现在我想生成一个列表,进行一些过滤,比如:salary>x并且salary<y,并按照员工姓名排序,如果有多个员工姓名相同但薪水不同,则再按照薪水排序。
到目前为止我已经完成的是:
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>

这里有两个 Mike,现在我想按照工资从高到低的顺序对他们进行排序,以得到以下结果:

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

除了 Mike,我不想改变其他订单。

但是我没有得到想要的结果,能否有人帮帮我,告诉我哪里出了问题,或者我需要从哪里进一步操作。谢谢 :)


1
有可能有两个薪水相同的Mike(假设他们出生年份不同)吗?如果可以,你想如何处理他们? - Pshemo
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Uraz Pokharel
1个回答

5
您可能正在寻找的是
.sorted(Comparator
        .comparing(Employee::getName)         //sort by name
        .thenComparing(Employee::getSalary))  //in case of same names sort by salary

如果您想使用降序,您可以创建一个单独的Comparator,它将基于Employee::getSalary进行comparing并使用其reversed()版本,例如:
        .sorted(Comparator
                .comparing(Employee::getName)
                .thenComparing(
                        Comparator.comparing(Employee::getSalary).reversed()
                )
        )

groupingByConcurrent(Employee::getName, LinkedHashMap::new, toList())

This will return a LinkedHashMap which preserves order of keys based on their insertion order.

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

或者,您可以将其分组到 TreeMap 中并跳过排序步骤... - Holger
@Holger 是的,至少我们可以跳过按名称排序的显式排序,因为 TreeMap 可以使用键的自然顺序。但是我们仍然需要对列表中的值进行排序。我之前考虑过将其添加到答案中,但决定让其他人作为单独的解决方案发布(所以请随意这样做)。 - Pshemo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接