我有一个班级
public class StudentVO {
int age;
String name;
}
我在两个不同的领域使用了同一个班级。在一个地方,我需要根据年龄排序。在另一个地方,我需要根据名称进行排序
另一个地方,我可能需要根据年龄和名称进行排序。我怎样才能做到这一点?
如果我可以覆盖一个字段compareTo()
。
是否可以这样做?
答案 0 :(得分:17)
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
的{{1}}有一些自然的排序顺序,请假设按StudentVO
排序。然后,对age
使用Comparable,age
使用Comparator
。
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
答案 1 :(得分:6)
在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'}]
答案 2 :(得分:1)
以下是代码段:
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
方法。
答案 3 :(得分:1)
在java中,您有两种比较对象的主要方法。 第一个是类本身实现Comparable接口,这意味着只有一个实现。 第二个是让类实现Comparator接口。这样,您可以为同一个类提供多个比较器。
这意味着您可以在StudentVo类上定义3个不同的比较器:一个仅比较名称,另一个比较年龄,最后一个比较两个属性。
在您的应用程序中,您可以根据要比较的内容使用适合您的实现。在一个地方,您将比较年龄Collections.sort(myStudents,new CompareStudentOnAge())的学生。在另一个地方,你使用另一个实现。
您可以在此博文中找到一些解释:http://javarevisited.blogspot.fr/2011/06/comparator-and-comparable-in-java.html
答案 4 :(得分:1)
我最近也必须解决这个问题。不确定这是否与您的情况完全相同,但我必须为网格的零列或更多列编写内存中的排序,在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<>();
}
留给你的想象力是解析各种各样的并构建链式比较器。实际上我把它变得有点复杂,因为我还根据需要通过交换链式比较器中子比较器的参数顺序来实现我实现的方向。
答案 5 :(得分:0)
安东的方法相当不错。我用这个:
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() ) );
答案 6 :(得分:0)
您可以使用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);