java 在java中对VO的多个动态字段使用Comparable
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16206629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Comparable for multiple dynamic fields of VO in java
提问by samba
I have a class
我有一堂课
public class StudentVO {
int age;
String name;
}
I used the same class in two different areas. At one place i need to sort based on the age. In another place I need to sort based on the name and in
another place i may need sorting based on both age and name. How can I do this?
If one field I can override compareTo()
.
我在两个不同的领域使用了同一个类。在一个地方,我需要根据年龄进行排序。在另一个地方,我需要根据姓名进行排序,而在另一个地方,我可能需要根据年龄和姓名进行排序。我怎样才能做到这一点?如果一个字段我可以覆盖compareTo()
.
Is it possible to do this?
是否有可能做到这一点?
回答by NINCOMPOOP
1)You should write two Comparatorfor sorting on age and name separately, and then use the Collections.sort(List,Comparator). Something like this:
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());
}
}
And then use them, To sort based on age
:
然后使用它们,基于以下进行排序age
:
Collections.sort(list,new AgeComparator());
to sort based on name
:
排序基于name
:
Collections.sort(list,new NameComparator());
2) If you think that the List
of StudentVO
has some natural order of sorting, say suppose sort by age
. Then, use Comparablefor age
and Comparator
for name
.
2) 如果您认为List
ofStudentVO
具有某种自然排序顺序,请假设 sort by age
。然后,使用Comparableforage
和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());
}
}
And then use them, To sort based on age
:
然后使用它们,基于以下进行排序age
:
Collections.sort(list);
to sort based on name
:
排序基于name
:
Collections.sort(list,new NameComparator());
回答by Anton Balaniuc
There is new approach for this in java-8
see Comparator#comparingand Comparator#thenComparing. All you need is to provide a lamda expression/method reference either to Stream#sorted()
or List#sort()
method.
java-8
请参阅Comparator#comparing和Comparator#thenComparing对此有新的方法。您所需要的只是提供对Stream#sorted()
或List#sort()
方法的 lamda 表达式/方法引用。
For example sorting by one field:
例如按一个字段排序:
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'}]
Sorting by a few fields:
按几个字段排序:
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'}]
回答by colin
I recently had to solve this problem, too. Not sure if this is exactly the same scenario as yours, but I had to write an in-memory sort for zero or more columns of a grid, handwaving over OOM conditions, etc, because my problem was very limited in scope.
我最近也不得不解决这个问题。不确定这是否与您的场景完全相同,但我必须为网格的零列或更多列编写内存排序,切换 OOM 条件等,因为我的问题范围非常有限。
I wrote a comparator for each column and a comparator that took a list of comparators. As I identified which columns needed to be sorted and in what order, I added an instance of the corresponding comparator to the list of comparators. Then, use the chained comparator to execute the actual sort.
我为每一列编写了一个比较器和一个比较器列表的比较器。当我确定哪些列需要排序以及按什么顺序排序时,我将相应比较器的实例添加到比较器列表中。然后,使用链式比较器执行实际排序。
public class MyObject
{
private String name;
private int age;
private Date registered;
}
So, something like this for each comparator:
因此,对于每个比较器,类似这样的事情:
public class NameComparator
implements Comparator<MyObject>
{
public int compare(MyObject o1, MyObject o2)
{
return o1.getName().compareTo(o2.getName);
}
}
This for the chained comparator:
这对于链式比较器:
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<>();
}
Left to your imagination is parsing the sorts and building the chained comparator. I actually made this a bit more complicated because I also incorporated a direction which I implemented by swapping the order of parameters in the call to the sub-comparator in the chained comparator as needed.
留给您的想象力是解析排序并构建链接的比较器。我实际上让这更复杂了一点,因为我还合并了一个方向,我通过根据需要交换调用中的参数顺序到链式比较器中的子比较器来实现。
回答by Kamil Chaber
Here is the code snippet:
这是代码片段:
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());
}
}
According to your question, it will also work when values of specified field will change. You have only to remember to call sort
method with this comparator.
根据您的问题,当指定字段的值发生变化时,它也会起作用。你只需要记住sort
用这个比较器调用方法。
回答by Quentin Proust
In java, you have two main way to compare objects. The first is for the class itself to implement the Comparableinterface which will mean only one implementations. The second is to have classes implements Comparatorinterface. This way, you can have multiple comparators for the same class.
在 Java 中,您有两种主要的方法来比较对象。第一个是类本身实现Comparable接口,这意味着只有一个实现。第二个是让类实现Comparator接口。这样,您可以为同一个类使用多个比较器。
This mean that you could define for exemple 3 diffenrent Comparators on your StudentVo class : one that compare only on the name, another that compare the ages and the last one that both properties.
这意味着您可以在 StudentVo 类上定义例如 3 个不同的比较器:一个只比较名称,另一个比较年龄,最后一个比较两个属性。
In your application, you use the implementation that suit you need based on what you want to compare. In one place, you will compare students on age Collections.sort(myStudents , new CompareStudentOnAge()). In another place, you use another implementation.
在您的应用程序中,您可以根据要比较的内容使用适合您的实现。在一处,您将比较年龄 Collections.sort(myStudents, new CompareStudentOnAge()) 上的学生。在另一个地方,您使用另一个实现。
You can find some explanations in this blog post : http://javarevisited.blogspot.fr/2011/06/comparator-and-comparable-in-java.html
您可以在这篇博文中找到一些解释:http: //javarevisited.blogspot.fr/2011/06/comparator-and-comparable-in-java.html
回答by Mohammad Eghlima
Anton's approach is quite good. I use this one:
安东的做法相当不错。我用这个:
1- For sorting only by age:
1- 仅按年龄排序:
Collections.sort( studentList, Comparator.comparingInt( student -> student.getAge() ) );
2- For name:
2- 对于名称:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ) );
3- Combination:
3-组合:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ).thenComparingInt( student -> student.getAge() ) );
回答by oat
You can cascade the comparators with thenComparing:
您可以使用 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);