如何按私人字段对列表进行排序?

Fan*_*nta 19 java sorting oop encapsulation list

我的实体类看起来像这样:

public class Student {

   private int grade;

   // other fields and methods
 }
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

List<Student> students = ...;
Run Code Online (Sandbox Code Playgroud)

我如何排序studentsgrade,考虑到这是一个私人领域?

sla*_*dan 42

你有这些选择:

  1. 使grade可见
  2. 为...定义一个getter方法 grade
  3. 定义一个Comparator 内部 Student
  4. 制作Student工具Comparable
  5. 使用反射(在我看来这不是一个解决方案,它是一个解决方法/黑客攻击)

解决方案示例3:

public class Student {
    private int grade;

    public static Comparator<Student> byGrade = Comparator.comparing(s -> s.grade);
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

List<Student> students = Arrays.asList(student2, student3, student1);
students.sort(Student.byGrade);
System.out.println(students);
Run Code Online (Sandbox Code Playgroud)

这是我最喜欢的解决方案因为:

  • 您可以轻松定义几个Comparators
  • 代码不多
  • 您的字段保持私有和封装

解决方案示例4:

public class Student implements Comparable {
    private int grade;

    @Override
    public int compareTo(Object other) {
        if (other instanceof Student) {
            return Integer.compare(this.grade, ((Student) other).grade);
        }
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以按到处是这样的:

List<Student> students = Arrays.asList(student2, student3, student1);
Collections.sort(students);
System.out.println(students);
Run Code Online (Sandbox Code Playgroud)

这个解决方案的方面:

  • 这定义了,sort by grade表示学生的自然顺序
  • 一些预先存在的方法会自动排序(如TreeMap)

  • 你甚至可以实现`Comparable`接口 (3认同)
  • *"可比较是一个好主意!"*也许,也许不是......这将决定学生的"自然顺序".有人可能会说学生成绩不能成为一个好的...; o) (2认同)

Bar*_*zKP 6

通常,如果您需要一个取决于学生成绩的行为,则必须可以访问此信息 - 添加允许其他代码访问它的方法或属性.

因此,最简单的解决方法是:

public class Student implements IStudent {

    ...
    private int grade;
    ...
    // other fields and methods

    public int getGrade() {
        return grade;
    }
}
Run Code Online (Sandbox Code Playgroud)

你应该扩展接口IStudent:)

但是,如果您只需要进行排序,则可以使用其他答案中已经提出的想法:实现Comparable界面.这样你可以保持grade隐藏,并在int compareTo方法中使用它.

  • @TimothyTruckle我不确定你在说什么.从DDD的角度来看,这些都是完全不同的世界.具有吸气剂或固定剂的DTO仅取决于您的工具/基础设施 - 如果从技术角度不需要它们,则不要添加它们.对于实体,您只需尝试创建一个合理的对象模型,其中包含getter/setter,从商业角度来看它们是有意义的. (2认同)
  • *"实施可比较的界面"*这将确定学生的"自然顺序".有人可能会说学生成绩不能成为一个好的...; o) (2认同)

aka*_*min 6

JDK 1.8提供的选项是使用streamsorted()方法,该方法不需要Comparable实现接口.您需要为字段实现accessor(getter)方法grade

public class Student {

private int grade;

public int getGrade() {
    return grade;
}

public Student setGrade(int grade) {
    this.grade = grade;
    return this;
}}
Run Code Online (Sandbox Code Playgroud)

然后给出unsortedStudentList你可以像下面的代码一样对它进行排序:

List<Student> sortedStudentList = unsortedStudentList
             .stream()
             .sorted(Comparator.comparing(Student::getGrade))
             .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

此外,sorted()方法还允许您根据其他字段(如果有)对学生进行排序.例如,考虑一个name学生的字段,在这种情况下,您希望根据年级和名称对studentList进行排序.所以Student上课会是这样的:

public class Student {

private int grade;
private String name;

public int getGrade() {
    return grade;
}

public Student setGrade(int grade) {
    this.grade = grade;
    return this;
}

public String getName() {
    return name;
}

public Student setName(String name) {
    this.name = name;
    return this;
}} 
Run Code Online (Sandbox Code Playgroud)

要根据这两个字段进行排序:

 List<Student> sortedStudentList = unsortedStudentList
              .stream()
              .sorted(Comparator.comparing(Student::getGrade)
              .thenComparing(Comparator.comparing(Student::getName)))
              .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

当第一个比较器比较两个相等的物体时,第二个比较器发挥作用.