我有一堂课
public class StudentVO {
int age;
String name;
}
我在两个不同的领域使用了相同的课程。在一个地方,我需要根据年龄进行排序。在另一个地方,我需要根据姓名进行排序,而在另一个地方,我可能需要根据年龄和姓名进行排序。我怎样才能做到这一点?如果一个字段我可以覆盖compareTo()
.
是否有可能做到这一点?
我有一堂课
public class StudentVO {
int age;
String name;
}
我在两个不同的领域使用了相同的课程。在一个地方,我需要根据年龄进行排序。在另一个地方,我需要根据姓名进行排序,而在另一个地方,我可能需要根据年龄和姓名进行排序。我怎样才能做到这一点?如果一个字段我可以覆盖compareTo()
.
是否有可能做到这一点?
1)您应该分别编写两个Comparator用于按年龄和姓名排序,然后使用Collections.sort(List,Comparator)。像这样的东西:
class StudentVO {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class AgeComparator implements Comparator<StudentVO> {
@Override
public int compare(StudentVO o1, StudentVO o2) {
Integer age1 = o1.getAge();
Integer age2 = o2.getAge();
return age1.compareTo(age2);
}
}
class NameComparator implements Comparator<StudentVO> {
@Override
public int compare(StudentVO o1, StudentVO o2) {
return o1.getName().compareTo(o2.getName());
}
}
然后使用它们,基于age
:
Collections.sort(list,new AgeComparator());
排序依据name
:
Collections.sort(list,new NameComparator());
2) 如果你认为List
ofStudentVO
有某种自然的排序顺序,假设 sort by age
。然后,使用Comparable forage
和Comparator
for name
。
class StudentVO implements Comparable<StudentVO>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(StudentVO o) {
return ((Integer)getAge()).compareTo(o.getAge());
}
}
class NameComparator implements Comparator<StudentVO> {
@Override
public int compare(StudentVO o1, StudentVO o2) {
return o1.getName().compareTo(o2.getName());
}
}
然后使用它们,基于age
:
Collections.sort(list);
排序依据name
:
Collections.sort(list,new NameComparator());
java-8
参见Comparator#comparing
和Comparator#thenComparing有新的方法。您所需要的只是为Stream#sorted()
或List#sort()
方法提供 lamda 表达式/方法引用。
例如按一个字段排序:
List<StudentVO> students = Arrays.asList(
new StudentVO(20,"Bob"),
new StudentVO(19, "Jane")
);
// sort by age
students.stream()
.sorted(Comparator.comparing(StudentVO::getAge))
.forEach(System.out::println);
// [StudentVO{age=19, name='Jane'},StudentVO{age=20, name='Bob'}]
// sort by name
students.stream()
.sorted(Comparator.comparing(StudentVO::getName))
.forEach(System.out::println);
// [StudentVO{age=20, name='Bob'}, StudentVO{age=19, name='Jane'}]
按几个字段排序:
List<StudentVO> students = Arrays.asList(
new StudentVO(20,"Bob"),
new StudentVO(19, "Jane"),
new StudentVO(21,"Bob")
);
// by age and then by name
students.stream()
.sorted(Comparator
.comparing(StudentVO::getAge)
.thenComparing(StudentVO::getName)
).forEach(System.out::println);
// [StudentVO{age=19, name='Jane'}, StudentVO{age=20, name='Bob'}, StudentVO{age=21, name='Bob'}]
// by name an then by age
students.stream()
.sorted(Comparator
.comparing(StudentVO::getName)
.thenComparing(StudentVO::getAge)
).forEach(System.out::println);
// [StudentVO{age=20, name='Bob'}, StudentVO{age=21, name='Bob'}, StudentVO{age=19, name='Jane'}]
我最近也不得不解决这个问题。不确定这是否与您的情况完全相同,但我不得不为网格的零列或多列编写内存排序,在 OOM 条件下进行手动操作等,因为我的问题范围非常有限。
我为每一列编写了一个比较器,并为一个比较器编写了一个比较器列表。当我确定需要对哪些列进行排序以及按什么顺序排序时,我将相应比较器的一个实例添加到比较器列表中。然后,使用链式比较器执行实际排序。
public class MyObject
{
private String name;
private int age;
private Date registered;
}
所以,每个比较器都是这样的:
public class NameComparator
implements Comparator<MyObject>
{
public int compare(MyObject o1, MyObject o2)
{
return o1.getName().compareTo(o2.getName);
}
}
这对于链式比较器:
public class ChainedComparator
implements Comparator<MyObject>
{
public int compare(MyObject o1, MyObject o2) {
for(Comparator<MyObject> comparator : comparators) {
int result = comparator.compare(o1,o2);
if(result != 0) {
return result;
}
}
return 0;
}
}
private List<Comparator<MyObject>> comparators = new ArrayList<>();
}
留给您的想象力是解析排序并构建链式比较器。实际上,我使这变得更复杂一些,因为我还合并了一个方向,我通过根据需要交换对链式比较器中的子比较器的调用中的参数顺序来实现该方向。
这是代码片段:
public class StudentNameComparator implements Comparator<StudentVO>{
@Override
public int compare(StudentVO s1, StudentVO s2) {
//ascending order
return s1.getName().compareTo(s2.getName());
//descending order
//return s2.getName().compareTo(s1.getName());
}
}
根据您的问题,当指定字段的值发生变化时,它也将起作用。你只需要记住sort
用这个比较器调用方法。
在 java 中,您有两种主要的方法来比较对象。第一个是类本身实现Comparable接口,这意味着只有一个实现。第二个是让类实现Comparator接口。这样,您可以为同一个类拥有多个比较器。
这意味着您可以在 StudentVo 类上定义例如 3 个不同的比较器:一个只比较名称,另一个比较年龄,最后一个比较两个属性。
在您的应用程序中,您可以根据要比较的内容使用适合您需要的实现。在一个地方,您将在年龄 Collections.sort(myStudents , new CompareStudentOnAge()) 上比较学生。在另一个地方,您使用另一个实现。
您可以在这篇博文中找到一些解释:http: //javarevisited.blogspot.fr/2011/06/comparator-and-comparable-in-java.html
安东的方法非常好。我用这个:
1-仅按年龄排序:
Collections.sort( studentList, Comparator.comparingInt( student -> student.getAge() ) );
2- 姓名:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ) );
3-组合:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ).thenComparingInt( student -> student.getAge() ) );
您可以使用 thenComparing 级联比较器:
List<File> files = new ArrayList();
Collections.sort(files,
new Comparator<File>() {
public int compare(File file1, File file2) {
return file2.getName()
.compareTo(file1.getName());
}
}.thenComparing(
new Comparator<File>() {
public int compare(File file1, File file2) {
return Long.valueOf(file2.getPath().length())
.compareTo(Long.valueOf(file1.getPath().length()));
}
}
)
);
// Collections.reverse(list);