java - 基于对象的不同可空字段的比较器

标签 java java-8 comparator

我有一个 Employee 对象,它包含两个字段 namejobTitle。对于员工对象排序,首先应优先考虑 jobTitle,如果 jobTitle 为 null,则应根据名称排序。

下面是Employee对象

public class Employee {
    private String name;
    private String jobTitle;
}

我使用链式比较器与 JobTitlecomparatorNameComparator 来实现这一点:

public class EmployeeChainedComparator implements Comparator<Employee> {

    private List<Comparator<Employee>> listComparators;

    @SafeVarargs
    public EmployeeChainedComparator(Comparator<Employee>... comparators) {
        this.listComparators = Arrays.asList(comparators);
    }

    @Override
    public int compare(Employee emp1, Employee emp2) {
        for (Comparator<Employee> comparator : listComparators) {
            int result = comparator.compare(emp1, emp2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }
}

public class EmployeeJobTitleComparator implements Comparator<Employee> {

    @Override
    public int compare(Employee emp1, Employee emp2) {
        if(emp1.getJobTitle() != null && emp2.getJobTitle() != null){
            return emp1.getJobTitle().compareTo(emp2.getJobTitle());
        } else {
            return 0;
        }
    }
}

public class EmployeeNameComparator implements Comparator<Employee> {

    @Override
    public int compare(Employee emp1, Employee emp2) {
        return emp1.getName().compareTo(emp2.getName());
    }
}

public class SortingMultipleAttributesExample {
    public static void main(String[] args) {
        List<Employee> listEmployees = new ArrayList<Employee>();
        listEmployees.add(new Employee("Tom", "Developer"));
        listEmployees.add(new Employee("Sam", null));
        listEmployees.add(new Employee("Tim", "Designer"));
        listEmployees.add(new Employee("Bob", null));
        listEmployees.add(new Employee("Peter", null));
        listEmployees.add(new Employee("Craig", "Programmer"));

        Collections.sort(listEmployees, new EmployeeChainedComparator(new EmployeeJobTitleComparator(), new EmployeeNameComparator()
                ));

        for(Employee emp : listEmployees){
            System.out.println("Employee Job: "+emp.getJobTitle()+" Employee Name: "+emp.getName());
        }
    }
}

现在我应该得到这样的输出

Employee Job: Designer Employee Name: Tim
Employee Job: Developer Employee Name: Tom
Employee Job: Programmer Employee Name: Craig
Employee Job: null Employee Name: Bob
Employee Job: null Employee Name: Peter
Employee Job null Employee Name: Sam

但我没有得到预期的结果。我得到这样的输出

Employee Job Developer Employee Name Tom
Employee Job null Employee Name Sam
Employee Job Designer Employee Name Tim
Employee Job null Employee Name Bob
Employee Job null Employee Name Peter
Employee Job Programmer Employee Name Craig

谁能帮我实现这个目标?

最佳答案

由于您使用的是 Java 8,因此您可以使用内置的比较器工具而不是创建自己的比较器。比较职位和名字可以很容易地完成

Comparator<Employee> comparator =
     Comparator.comparing(Employee::getJobTitle).thenComparing(Employee:getName);

如何处理 null 值也内置于 nullsLast 中和 nullsFirst方法。这些方法将现有比较器包装到 null 安全比较器中,将 null 值放在末尾或开头。

因此,您可以:

import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;

// ...

Comparator<Employee> comparator = 
    comparing(Employee::getJobTitle, nullsLast(naturalOrder())).thenComparing(Employee::getName);

Collections.sort(listEmployees, comparator);

比较器由 comparing 创建带有 null 安全比较器的职位头衔将 null 值放在最后 ( see also )。对于相同的标题,它是 thenComparing员工姓名。

关于java - 基于对象的不同可空字段的比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39518961/

相关文章:

java - Collectors (Java) 中的 groupingby 和映射有什么区别?

java - 使用 java 比较器但具有固定值的对象排序应该在排序列表中的最后一个值中

java - JPanel 在设置为图标数组时不显示标签,但在设置为单个图标时会显示

java - 从Java中的另一个类访问图形渲染方法

java - 我如何创建一个 HashMap 来迭代 lambda 函数?

java-8 - jdk 11 中缺少外部 jar 文件

java - 在集合中排序比较器/可比较

java - 优化排序方法

java - 尝试加载文件时出现 JMagick 错误 - UnsatisfiedLink

java - Hibernate一对一映射不获取父类的子类数据