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 t
Anton's approach is quite good. I use this one:
1- For sorting only by age:
Collections.sort( studentList, Comparator.comparingInt( student -> student.getAge() ) );
2- For name:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ) );
3- Combination:
Collections.sort( studentList, Comparator.comparing( student -> student.getName() ).thenComparingInt( student -> student.getAge() ) );
You can cascade the comparators with 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);
https://www.eovao.com/en/a/sort%20elements%20java/4/how-to-sort-objects-in-java---multiple-comparison-sort-list
1)You should write two Comparator for sorting on age and name separately, and then use the Collections.sort(List,Comparator). Something like this:
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
:
Collections.sort(list,new AgeComparator());
to sort based on 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 Comparable for age
and 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
:
Collections.sort(list);
to sort based on name
:
Collections.sort(list,new NameComparator());
There is new approach for this in java-8
see Comparator#comparing
and Comparator#thenComparing. All you need is to provide a lamda expression/method reference either to Stream#sorted()
or List#sort()
method.
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'}]
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.
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.
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.