Create a comparator class to handle sorting:
private class MyObjectComparator<MyObject> implements Comparator<MyObject> {
/**
* {@inheritDoc}
*/
@Override
public int compare(MyObject o1, MyObject o2) {
return o2.getSequenceNumber() - o1.getSequenceNumber();
}
}
Then sort your ArrayList with it:
Collections.sort(myArrayList, new MyObjectComparator());
Answer from Adam on Stack OverflowCreate a comparator class to handle sorting:
private class MyObjectComparator<MyObject> implements Comparator<MyObject> {
/**
* {@inheritDoc}
*/
@Override
public int compare(MyObject o1, MyObject o2) {
return o2.getSequenceNumber() - o1.getSequenceNumber();
}
}
Then sort your ArrayList with it:
Collections.sort(myArrayList, new MyObjectComparator());
You can use lambda expression introduced in Java8 to sort objects without implementing Comparable/Comparator interface.
Below is the code snippet to sort and display objects using lambda.
class Student
{
int id;
String name;
public Student(int id, String name)
{
this.id = id;
this.name = name;
}
public String toString()
{
return id +" " +name;
}
}
public class SortDemo
{
public static void main(String[] args)
{
List<Student> list=new ArrayList<Student>();
//Adding Objects
list.add(new Student(1,"XYZ"));
list.add(new Student(3,"ABC"));
list.add(new Student(2,"PQR"));
System.out.println("Sorting on the basis of name...");
// implementing lambda expression
Collections.sort(list,(p1,p2)->{return p1.name.compareTo(p2.name);});
list.forEach((s)->System.out.println(s));
}
}
Videos
here is my "1liner":
Collections.sort(agentDtoList, new Comparator<AgentSummaryDTO>(){
public int compare(AgentSummaryDTO o1, AgentSummaryDTO o2){
return o1.getCustomerCount() - o2.getCustomerCount();
}
});
UPDATE for Java 8: For int datatype
Collections.sort(agentDtoList, (o1, o2) -> o1.getCustomerCount() - o2.getCustomerCount());
or even:
Collections.sort(agentDtoList, Comparator.comparing(AgentSummaryDTO::getCustomerCount));
For String datatype (as in comment)
Collections.sort(list, (o1, o2) -> (o1.getAgentName().compareTo(o2.getAgentName())));
..it expects getter AgentSummaryDTO.getCustomerCount()
for anyone who looks for answer yet:
you can also sort your list with JAVA-8 Stream-API.
List<AgentSummaryDTO> sortedList = agentDtoList.stream()
.sorted(Comparator.comparing(AgentSummaryDTO::getCustomerCount).reversed())
.collect(Collectors.toList());
Assuming you actually have a List<AnObject>, all you need is
list.sort(Comparator.comparing(a -> a.attr));
If you make you code clean by not using public fields, but accessor methods, it becomes even cleaner:
list.sort(Comparator.comparing(AnObject::getAttr));
As a complement to @JB Nizet's answer, if your attr is nullable,
list.sort(Comparator.comparing(AnObject::getAttr));
may throw a NPE.
If you also want to sort null values, you can consider
list.sort(Comparator.comparing(a -> a.attr, Comparator.nullsFirst(Comparator.naturalOrder())));
or
list.sort(Comparator.comparing(a -> a.attr, Comparator.nullsLast(Comparator.naturalOrder())));
which will put nulls first or last.
How do i alphabetically sort an arraylist of objects, based on the objects field "name". I have object Car, with a compareTo method:
@Override
public int compareTo(Car cName) {
int last = this.carName.compareTo(cName.carName);
return last == 0 ? this.carName.compareTo(cName.carName) : last;
}In a separate class there is an array list that captures all of these Car Objects. I need to sort that list alphabetically, then print out the table of Car Objects in alphabetical order. Im stuck trying to implement the above into the sort for the arraylist that i will iteratively print over.
I have looked at Collections.sort() but i don't want to edit the class name to implement comparator.
public void printRacers() {
// get
//
ArrayList<Car> carNames = new ArrayList<>();
carNames.addAll(racers);
System.out.println("Car name Race Car number");
for (int i = 0; i < carNames.size(); i++) {
Car c = carNames.get(i);
String cName = c.getCarName();
String cRace = d.getRaceName();
int sNum = c.getCarNumber();
String outputString = cName + " " + cClass + " " + sNum;
System.out.println(outputString);
}Im really stuck on this and would appreciate anyone's help!
Thanks
Since Date implements Comparable, it has a compareTo method just like String does.
So your custom Comparator could look like this:
public class CustomComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject o1, MyObject o2) {
return o1.getStartDate().compareTo(o2.getStartDate());
}
}
The compare() method must return an int, so you couldn't directly return a boolean like you were planning to anyway.
Your sorting code would be just about like you wrote:
Collections.sort(Database.arrayList, new CustomComparator());
A slightly shorter way to write all this, if you don't need to reuse your comparator, is to write it as an inline anonymous class:
Collections.sort(Database.arrayList, new Comparator<MyObject>() {
@Override
public int compare(MyObject o1, MyObject o2) {
return o1.getStartDate().compareTo(o2.getStartDate());
}
});
Since java-8
You can now write the last example in a shorter form by using a lambda expression for the Comparator:
Collections.sort(Database.arrayList,
(o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
And List has a sort(Comparator) method, so you can shorten this even further:
Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
This is such a common idiom that there's a built-in method to generate a Comparator for a class with a Comparable key:
Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));
All of these are equivalent forms.
Classes that has a natural sort order (a class Number, as an example) should implement the Comparable interface, whilst classes that has no natural sort order (a class Chair, as an example) should be provided with a Comparator (or an anonymous Comparator class).
Two examples:
public class Number implements Comparable<Number> {
private int value;
public Number(int value) { this.value = value; }
public int compareTo(Number anotherInstance) {
return this.value - anotherInstance.value;
}
}
public class Chair {
private int weight;
private int height;
public Chair(int weight, int height) {
this.weight = weight;
this.height = height;
}
/* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
public int compare(Chair chair1, Chair chair2) {
return chair1.getWeight() - chair2.getWeight();
}
}
class ChairHeightComparator implements Comparator<Chair> {
public int compare(Chair chair1, Chair chair2) {
return chair1.getHeight() - chair2.getHeight();
}
}
Usage:
List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);
List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());
// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
public int compare(Chair chair1, Chair chair2) {
...
}
});
Your Comparator would look like this:
public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> {
public int compare(GraduationCeremony o1, GraduationCeremony o2) {
int value1 = o1.campus.compareTo(o2.campus);
if (value1 == 0) {
int value2 = o1.faculty.compareTo(o2.faculty);
if (value2 == 0) {
return o1.building.compareTo(o2.building);
} else {
return value2;
}
}
return value1;
}
}
Basically it continues comparing each successive attribute of your class whenever the compared attributes so far are equal (== 0).
Yes, you absolutely can do this. For example:
public class PersonComparator implements Comparator<Person>
{
public int compare(Person p1, Person p2)
{
// Assume no nulls, and simple ordinal comparisons
// First by campus - stop if this gives a result.
int campusResult = p1.getCampus().compareTo(p2.getCampus());
if (campusResult != 0)
{
return campusResult;
}
// Next by faculty
int facultyResult = p1.getFaculty().compareTo(p2.getFaculty());
if (facultyResult != 0)
{
return facultyResult;
}
// Finally by building
return p1.getBuilding().compareTo(p2.getBuilding());
}
}
Basically you're saying, "If I can tell which one comes first just by looking at the campus (before they come from different campuses, and the campus is the most important field) then I'll just return that result. Otherwise, I'll continue on to compare faculties. Again, stop if that's enough to tell them apart. Otherwise, (if the campus and faculty are the same for both people) just use the result of comparing them by building."