Related
I have simple class
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
and List<ActiveAlarm> con. How to sort in ascending order by timeStarted, then by timeEnded? Can anybody help? I know in C++ with generic algorithm and overload operator <, but I am new to Java.
Using Comparator
For Example:
class Score {
private String name;
private List<Integer> scores;
// +accessor methods
}
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
With Java 8 onwards, you can simply use lambda expression to represent Comparator instance.
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
Either make ActiveAlarm implement Comparable<ActiveAlarm> or implement Comparator<ActiveAlarm> in a separate class. Then call:
Collections.sort(list);
or
Collections.sort(list, comparator);
In general, it's a good idea to implement Comparable<T> if there's a single "natural" sort order... otherwise (if you happen to want to sort in a particular order, but might equally easily want a different one) it's better to implement Comparator<T>. This particular situation could go either way, to be honest... but I'd probably stick with the more flexible Comparator<T> option.
EDIT: Sample implementation:
public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
#Override
public int compare(ActiveAlarm x, ActiveAlarm y) {
// TODO: Handle null x or y values
int startComparison = compare(x.timeStarted, y.timeStarted);
return startComparison != 0 ? startComparison
: compare(x.timeEnded, y.timeEnded);
}
// I don't know why this isn't in Long...
private static int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
JAVA 8 and Above Answer (Using Lambda Expressions)
In Java 8, Lambda expressions were introduced to make this even easier! Instead of creating a Comparator() object with all of it's scaffolding, you can simplify it as follows: (Using your object as an example)
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);
or even shorter:
Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));
That one statement is equivalent to the following:
Collections.sort(list, new Comparator<ActiveAlarm>() {
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return a1.timeStarted - a2.timeStarted;
}
});
Think of Lambda expressions as only requiring you to put in the relevant parts of the code: the method signature and what gets returned.
Another part of your question was how to compare against multiple fields. To do that with Lambda expressions, you can use the .thenComparing() function to effectively combine two comparisons into one:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
The above code will sort the list first by timeStarted, and then by timeEnded (for those records that have the same timeStarted).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing() function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places
If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
public int compare(ActiveAlarm o1, ActiveAlarm o2) {
//Sorts by 'TimeStarted' property
return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
}
//If 'TimeStarted' property is equal sorts by 'TimeEnded' property
public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property:
write a class that implements 'Comparable' and override 'compareTo' method as defined below
class ActiveAlarm implements Comparable<ActiveAlarm>{
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(long timeStarted,long timeEnded) {
this.timeStarted=timeStarted;
this.timeEnded=timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
public int compareTo(ActiveAlarm o) {
return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}
public int doSecodaryOrderSort(ActiveAlarm o) {
return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows:
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
public class ActiveAlarm implements Comparable<ActiveAlarm> {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public int compareTo(ActiveAlarm a) {
if ( this.timeStarted > a.timeStarted )
return 1;
else if ( this.timeStarted < a.timeStarted )
return -1;
else {
if ( this.timeEnded > a.timeEnded )
return 1;
else
return -1;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort() on the list.
Since Java8 this can be done even cleaner using a combination of Comparator and Lambda expressions
For Example:
class Student{
private String name;
private List<Score> scores;
// +accessor methods
}
class Score {
private int grade;
// +accessor methods
}
Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
Java-8 solution using Stream API:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B. When timeStarted and timeEnded have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
If you want to sort the original list itself:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B. When timeStarted and timeEnded have public getter methods:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
Guava's ComparisonChain:
Collections.sort(list, new Comparator<ActiveAlarm>(){
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return ComparisonChain.start()
.compare(a1.timestarted, a2.timestarted)
//...
.compare(a1.timeEnded, a1.timeEnded).result();
}});
We can use the Comparator.comparing() method to sort a list based on an object's property.
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
Note that before doing it, you'll have to define at least the getter methods of the properties you want to base your sort on.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
#Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
Employee POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Employee Class To Manage Employee
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
Custom Sorting
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
You can use Collections.sort and pass your own Comparator<ActiveAlarm>
In java you need to use the static Collections.sort method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
#Override
public int compare(Object o1, Object o2) {
int x1 = ((CompanyRole) o1).getBegin();
int x2 = ((CompanyRole) o2).getBegin();
if (x1 != x2) {
return x1 - x2;
} else {
int y1 = ((CompanyRole) o1).getEnd();
int y2 = ((CompanyRole) o2).getEnd();
return y2 - y1;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
As mentioned you can sort by:
Making your object implement Comparable
Or pass a Comparator to Collections.sort
If you do both, the Comparable will be ignored and Comparator will be used. This helps that the value objects has their own logical Comparable which is most reasonable sort for your value object, while each individual use case has its own implementation.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
List<ActiveAlarm> con = new ArrayList<ActiveAlarm>();
Collections.sort(con , (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted));
Collections.sort(con , (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
Here's what did the trick for me.
Was much shorter and easier than everything else I found:
Collections.sort(listName, Comparator.comparing(Object::getProperty).reversed());
The ".reversed()" part at the end was a requirement for my specific project but I'm sharing it too, as it took a while to find it
The best and the easiest way to sort any list of objects in Java (Java 8 and above).
Lets sort a basket of fruits based on the property "fruitName"
Fruit POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
#Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
Now lets add fruits into a list and then sort it
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
You can now print the list (i.e basketOfFruits) and the fruits in the list would be sorted in ASCENDING order (lexicographically).
The output would look like this:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
Instead of Collections.sort(), Java streams can also be used (Java 8 and above). The following is the code using Java streams
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
here the list is sorted in the same manner as Collections.sort(), but the sorted items would be stored/collected in another list "sortedFruits". So, if we want to print the sorted items of the list, we need to print "sortedFruits" instead of "basketOfFruits" in this case
I have simple class
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
and List<ActiveAlarm> con. How to sort in ascending order by timeStarted, then by timeEnded? Can anybody help? I know in C++ with generic algorithm and overload operator <, but I am new to Java.
Using Comparator
For Example:
class Score {
private String name;
private List<Integer> scores;
// +accessor methods
}
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
With Java 8 onwards, you can simply use lambda expression to represent Comparator instance.
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
Either make ActiveAlarm implement Comparable<ActiveAlarm> or implement Comparator<ActiveAlarm> in a separate class. Then call:
Collections.sort(list);
or
Collections.sort(list, comparator);
In general, it's a good idea to implement Comparable<T> if there's a single "natural" sort order... otherwise (if you happen to want to sort in a particular order, but might equally easily want a different one) it's better to implement Comparator<T>. This particular situation could go either way, to be honest... but I'd probably stick with the more flexible Comparator<T> option.
EDIT: Sample implementation:
public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
#Override
public int compare(ActiveAlarm x, ActiveAlarm y) {
// TODO: Handle null x or y values
int startComparison = compare(x.timeStarted, y.timeStarted);
return startComparison != 0 ? startComparison
: compare(x.timeEnded, y.timeEnded);
}
// I don't know why this isn't in Long...
private static int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
JAVA 8 and Above Answer (Using Lambda Expressions)
In Java 8, Lambda expressions were introduced to make this even easier! Instead of creating a Comparator() object with all of it's scaffolding, you can simplify it as follows: (Using your object as an example)
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);
or even shorter:
Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));
That one statement is equivalent to the following:
Collections.sort(list, new Comparator<ActiveAlarm>() {
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return a1.timeStarted - a2.timeStarted;
}
});
Think of Lambda expressions as only requiring you to put in the relevant parts of the code: the method signature and what gets returned.
Another part of your question was how to compare against multiple fields. To do that with Lambda expressions, you can use the .thenComparing() function to effectively combine two comparisons into one:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
The above code will sort the list first by timeStarted, and then by timeEnded (for those records that have the same timeStarted).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing() function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places
If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
public int compare(ActiveAlarm o1, ActiveAlarm o2) {
//Sorts by 'TimeStarted' property
return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
}
//If 'TimeStarted' property is equal sorts by 'TimeEnded' property
public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property:
write a class that implements 'Comparable' and override 'compareTo' method as defined below
class ActiveAlarm implements Comparable<ActiveAlarm>{
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(long timeStarted,long timeEnded) {
this.timeStarted=timeStarted;
this.timeEnded=timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
public int compareTo(ActiveAlarm o) {
return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}
public int doSecodaryOrderSort(ActiveAlarm o) {
return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows:
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
public class ActiveAlarm implements Comparable<ActiveAlarm> {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public int compareTo(ActiveAlarm a) {
if ( this.timeStarted > a.timeStarted )
return 1;
else if ( this.timeStarted < a.timeStarted )
return -1;
else {
if ( this.timeEnded > a.timeEnded )
return 1;
else
return -1;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort() on the list.
Since Java8 this can be done even cleaner using a combination of Comparator and Lambda expressions
For Example:
class Student{
private String name;
private List<Score> scores;
// +accessor methods
}
class Score {
private int grade;
// +accessor methods
}
Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
Java-8 solution using Stream API:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B. When timeStarted and timeEnded have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
If you want to sort the original list itself:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B. When timeStarted and timeEnded have public getter methods:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
Guava's ComparisonChain:
Collections.sort(list, new Comparator<ActiveAlarm>(){
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return ComparisonChain.start()
.compare(a1.timestarted, a2.timestarted)
//...
.compare(a1.timeEnded, a1.timeEnded).result();
}});
We can use the Comparator.comparing() method to sort a list based on an object's property.
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
Note that before doing it, you'll have to define at least the getter methods of the properties you want to base your sort on.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
#Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
Employee POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Employee Class To Manage Employee
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
Custom Sorting
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
You can use Collections.sort and pass your own Comparator<ActiveAlarm>
In java you need to use the static Collections.sort method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
#Override
public int compare(Object o1, Object o2) {
int x1 = ((CompanyRole) o1).getBegin();
int x2 = ((CompanyRole) o2).getBegin();
if (x1 != x2) {
return x1 - x2;
} else {
int y1 = ((CompanyRole) o1).getEnd();
int y2 = ((CompanyRole) o2).getEnd();
return y2 - y1;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
As mentioned you can sort by:
Making your object implement Comparable
Or pass a Comparator to Collections.sort
If you do both, the Comparable will be ignored and Comparator will be used. This helps that the value objects has their own logical Comparable which is most reasonable sort for your value object, while each individual use case has its own implementation.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
List<ActiveAlarm> con = new ArrayList<ActiveAlarm>();
Collections.sort(con , (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted));
Collections.sort(con , (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
The best and the easiest way to sort any list of objects in Java (Java 8 and above).
Lets sort a basket of fruits based on the property "fruitName"
Fruit POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
#Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
Now lets add fruits into a list and then sort it
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
You can now print the list (i.e basketOfFruits) and the fruits in the list would be sorted in ASCENDING order (lexicographically).
The output would look like this:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
Instead of Collections.sort(), Java streams can also be used (Java 8 and above). The following is the code using Java streams
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
here the list is sorted in the same manner as Collections.sort(), but the sorted items would be stored/collected in another list "sortedFruits". So, if we want to print the sorted items of the list, we need to print "sortedFruits" instead of "basketOfFruits" in this case
I have simple class
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
and List<ActiveAlarm> con. How to sort in ascending order by timeStarted, then by timeEnded? Can anybody help? I know in C++ with generic algorithm and overload operator <, but I am new to Java.
Using Comparator
For Example:
class Score {
private String name;
private List<Integer> scores;
// +accessor methods
}
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
With Java 8 onwards, you can simply use lambda expression to represent Comparator instance.
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
Either make ActiveAlarm implement Comparable<ActiveAlarm> or implement Comparator<ActiveAlarm> in a separate class. Then call:
Collections.sort(list);
or
Collections.sort(list, comparator);
In general, it's a good idea to implement Comparable<T> if there's a single "natural" sort order... otherwise (if you happen to want to sort in a particular order, but might equally easily want a different one) it's better to implement Comparator<T>. This particular situation could go either way, to be honest... but I'd probably stick with the more flexible Comparator<T> option.
EDIT: Sample implementation:
public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
#Override
public int compare(ActiveAlarm x, ActiveAlarm y) {
// TODO: Handle null x or y values
int startComparison = compare(x.timeStarted, y.timeStarted);
return startComparison != 0 ? startComparison
: compare(x.timeEnded, y.timeEnded);
}
// I don't know why this isn't in Long...
private static int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
JAVA 8 and Above Answer (Using Lambda Expressions)
In Java 8, Lambda expressions were introduced to make this even easier! Instead of creating a Comparator() object with all of it's scaffolding, you can simplify it as follows: (Using your object as an example)
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);
or even shorter:
Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));
That one statement is equivalent to the following:
Collections.sort(list, new Comparator<ActiveAlarm>() {
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return a1.timeStarted - a2.timeStarted;
}
});
Think of Lambda expressions as only requiring you to put in the relevant parts of the code: the method signature and what gets returned.
Another part of your question was how to compare against multiple fields. To do that with Lambda expressions, you can use the .thenComparing() function to effectively combine two comparisons into one:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
The above code will sort the list first by timeStarted, and then by timeEnded (for those records that have the same timeStarted).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing() function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places
If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
public int compare(ActiveAlarm o1, ActiveAlarm o2) {
//Sorts by 'TimeStarted' property
return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
}
//If 'TimeStarted' property is equal sorts by 'TimeEnded' property
public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property:
write a class that implements 'Comparable' and override 'compareTo' method as defined below
class ActiveAlarm implements Comparable<ActiveAlarm>{
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(long timeStarted,long timeEnded) {
this.timeStarted=timeStarted;
this.timeEnded=timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
public int compareTo(ActiveAlarm o) {
return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}
public int doSecodaryOrderSort(ActiveAlarm o) {
return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows:
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
public class ActiveAlarm implements Comparable<ActiveAlarm> {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public int compareTo(ActiveAlarm a) {
if ( this.timeStarted > a.timeStarted )
return 1;
else if ( this.timeStarted < a.timeStarted )
return -1;
else {
if ( this.timeEnded > a.timeEnded )
return 1;
else
return -1;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort() on the list.
Since Java8 this can be done even cleaner using a combination of Comparator and Lambda expressions
For Example:
class Student{
private String name;
private List<Score> scores;
// +accessor methods
}
class Score {
private int grade;
// +accessor methods
}
Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
Java-8 solution using Stream API:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B. When timeStarted and timeEnded have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
If you want to sort the original list itself:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B. When timeStarted and timeEnded have public getter methods:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
Guava's ComparisonChain:
Collections.sort(list, new Comparator<ActiveAlarm>(){
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return ComparisonChain.start()
.compare(a1.timestarted, a2.timestarted)
//...
.compare(a1.timeEnded, a1.timeEnded).result();
}});
We can use the Comparator.comparing() method to sort a list based on an object's property.
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
Note that before doing it, you'll have to define at least the getter methods of the properties you want to base your sort on.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
#Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
Employee POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Employee Class To Manage Employee
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
Custom Sorting
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
You can use Collections.sort and pass your own Comparator<ActiveAlarm>
In java you need to use the static Collections.sort method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
#Override
public int compare(Object o1, Object o2) {
int x1 = ((CompanyRole) o1).getBegin();
int x2 = ((CompanyRole) o2).getBegin();
if (x1 != x2) {
return x1 - x2;
} else {
int y1 = ((CompanyRole) o1).getEnd();
int y2 = ((CompanyRole) o2).getEnd();
return y2 - y1;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
As mentioned you can sort by:
Making your object implement Comparable
Or pass a Comparator to Collections.sort
If you do both, the Comparable will be ignored and Comparator will be used. This helps that the value objects has their own logical Comparable which is most reasonable sort for your value object, while each individual use case has its own implementation.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
List<ActiveAlarm> con = new ArrayList<ActiveAlarm>();
Collections.sort(con , (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted));
Collections.sort(con , (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
Here's what did the trick for me.
Was much shorter and easier than everything else I found:
Collections.sort(listName, Comparator.comparing(Object::getProperty).reversed());
The ".reversed()" part at the end was a requirement for my specific project but I'm sharing it too, as it took a while to find it
The best and the easiest way to sort any list of objects in Java (Java 8 and above).
Lets sort a basket of fruits based on the property "fruitName"
Fruit POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
#Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
Now lets add fruits into a list and then sort it
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
You can now print the list (i.e basketOfFruits) and the fruits in the list would be sorted in ASCENDING order (lexicographically).
The output would look like this:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
Instead of Collections.sort(), Java streams can also be used (Java 8 and above). The following is the code using Java streams
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
here the list is sorted in the same manner as Collections.sort(), but the sorted items would be stored/collected in another list "sortedFruits". So, if we want to print the sorted items of the list, we need to print "sortedFruits" instead of "basketOfFruits" in this case
I would like to sort the Items of a JComboBox by it's items attributs :
I have this class :
public class Person {
private static _ID;
private _Name;
private _FamilyName;
public MyObject (int id, String name, String familyName){
_ID = id;
_Name = name;
_FamilyName = familyName;
}
#Override
public toString (){
return _Name;
}
}
And I have a JComboBox :
JComboBox comboBox = new JComboBox();
comboBox.addItem( new Person(1,"Richard","Stallman") );
comboBox.addItem( new Person(2,"Douglas","Adams") );
comboBox.addItem( new Person(3,"Terry","Pratchett") );
comboBox.addItem( new Person(4,"Goreges","Brassens") );
I would like the user to choose the way he wants to sort the JComboBox:
JComboBox comboBoxSort = new JComboBox();
comboBoxSort.addItemSort("ID");
comboBoxSort.addItemSort("Name");
comboBoxSort.addItemSort("Family Name");
I don't need to change the displayed value in the JComboBox, I just need the order to change.
You should be able to use the Sorted Combo Box Model.
It will sort by default on the natural sort order of the object added to the model, or you can provide a custom Comparator.
First thing, your Person class is syntactically wrong. Here's a corrected version.
public class Person {
private static int _ID_COUNTER = 0;
private int _ID;
private String _Name;
private String _FamilyName;
public Person(String name, String familyName) {
_ID = ++ID_COUNTER;
_Name = name;
_FamilyName = familyName;
}
#Override
public String toString() {
return _Name;
}
public int get_ID() {
return _ID;
}
public String get_Name() {
return _Name;
}
public String get_FamilyName() {
return _FamilyName;
}
}
The Sorted Combo Box Model that camickr mentioned allows you to sort the Person instances in one way. To sort the Person instances 3 different ways, you'll need to write 3 Comparator classes. Here's one for the name.
public class NameSort implements Comparator<Person> {
#Override
public int compare(Person arg0, Person arg1) {
int result = arg0.get_Name().compareToIgnoreCase(arg1.get_Name());
if (result == 0) {
return arg0.get_FamilyName().compareToIgnoreCase(
arg1.get_FamilyName());
} else {
return result;
}
}
}
You should be able to write the other 2 Comparator classes.
Finally, you need to sort the input to the JComboBox. The easiest way to do this is to keep a List<Person> and pass a sorted Person[] to the JComboBox. Here's one way to do that.
public Person[] sortPersonsByName(List<Person> persons) {
Collections.sort(persons, new NameSort());
return persons.toArray(new Person[persons.size()]);
}
This code would be called in the action listener of your sort JButton.
I have a list of java beans, now I want to sort them with specified property and sort order
(the property and sort order are input parameters), like this:
class Person{
private String userName;
private Integer age;
private String address;
public void sort(List<Person> ps, String property, String sortOrder)
{
// How to use the property and sortOrder??
Collections.sort(ps);
}
}
What is the best way of writing the sortList() method?
actually I have one way to do this. I can write two static properties for Person. then I set these two properties before sorting:
class Person implements Comparable<Person>{
private String userName;
private Integer age;
private String address;
public static String sortProperty;
public static String sortOrder;
public void sort(List<Person> ps, String property, String sortOrder)
{
Person.sortProperty=property;
Person.sortOrder=sortOrder;
Collections.sort(ps);
}
#Override
public int compareTo(Person o)
{
// find the property with Person.sortProperty using reflection
// then sort the property
}
}
This is not a good solution. Could anyone give me some suggestion? thanks in advance
Hope this makes sense for you. Use final keyword to avoid creating static variable for passing sort order. Also changed it to boolean for easy access. Below code is just for illustration.
public static void sort(List<Person> ps, String property, final boolean asc) {
if (property.equals("userName")) {
Collections.sort(ps, new Comparator<Person>() {
public int compare(Person o1, Person o2) {
// pls use appropriate compareTo I always get confused
// which one to call when it is asc or desc.
if (asc)
return o1.getUserName().compareTo(o2.getUserName());
else
return o2.getUserName().compareTo(o1.getUserName());
}
});
}
if (property.equals("age")) {
Collections.sort(ps, new Comparator<Person>() {
public int compare(Person o1, Person o2) {
if (asc)
return o1.getAge().compareTo(o2.getAge());
else
return o2.getAge().compareTo(o1.getAge());
}
});
}
}
You can implement a Comparator and use it like this.
Collections.sort(ps, myComparator)
Inside the comparator you can just retrieve property and sortOrder from person and compare with these variable
Collections.sort(ps, new Comparator<Person>() {
#Override
public int compare(Person p1, Person p2) {
int result = 0;
if(sortProperty.equals("userName")) {
result = p1.userName.compareTo(p2.userName);
} else if(//...
//determine how based on sortOrder here
//e.g.
if(sortOrder.equals("ascending") {
return result;
} else {
return (result * (-1));
}
}
});
Note: property and sortOrder need to be declared final.
You should be able to use the Bean Comparator for this.
Write three Comparators. They could be static fields. E.g.
public static final Comparator COMPARE_BY_NAME = (your code here)
And similar for COMPARE_BY_AGE etc.
Pass them to the standard Java sort() methods.
To make the sorting as generic extended method of a list you can use below code:
public static List<T> SortList<T>(this List<T> list, string sortDirection, string sortExpression)
{
if (sortDirection.ToLower() == "sorting_asc")
{
return (from n in list
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n
).ToList();
}
else if (sortDirection.ToLower() == "sorting_desc")
{
return (from n in list
orderby GetDynamicSortProperty(n, sortExpression) descending
select n
).ToList();
}
else
{
return list;
}
}
public static object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}
Calling:
List<Employee> employees = new List<Employee>();
var sortedEmployees = employees.SortList(sortedorder, sortedcolumn);