In this tutorial, we’re gonna look at some useful ways to sort Java ArrayList of Objects for Ascending and Descending order. You will know how to:
- sort ArrayList of Objects by one field or multiple fields
- use custom
Comparator
to sort ArrayList of Objects - implement
Comparable
interface to sort ArrayList of Objects conveniently
Contents
Java ArrayList of Objects
ArrayList is a part of collection framework and we can find it in java.util
package. We can think about Java ArrayList as dynamic Array of items.
Let’s create a Class for our examples first.
package com.bezkoder.java.arraylist.sorting;
public class Date {
private String name;
private int year;
private int month;
public Date(String name, int year, int month) {
this.name = name;
this.year = year;
this.month = month;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
@Override
public String toString() {
return "Date [name=" + name + ", year=" + year + ", month=" + month + "]";
}
}
Then we create an ArrayList
of Date
objects and add items to it.
ArrayList<Date> dates = new ArrayList<>();
dates.add(new Date("DDD", 2020, 2));
dates.add(new Date("AAA", 2022, 11));
dates.add(new Date("ZZZ", 2020, 5));
dates.add(new Date("AAA", 2021, 8));
dates.add(new Date("AAA", 2021, 6));
dates.add(new Date("DDD", 2021, 2));
dates.add(new Date("ZZZ", 2020, 3));
That’s all we need to prepare. In the next sections, I will show you many ways to sort the ArrayList
of Objects above.
Sort ArrayList of Objects by field in Java
Now we’re gonna sort ArrayList
of Date
items by field name
(and don’t care about other fields).
Collections.sort()
You can use Collections.sort() with Comparator.comparing().
The Comparator.comparing()
method accepts a method reference for the comparison. So you can pass Date::getName
to sort by the name
field.
Collections.sort(dates, Comparator.comparing(Date::getName));
dates.forEach(System.out::println);
/*
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
*/
For Descending order, we use Collections.reverse() on the sorted ArrayList by Ascending:
Collections.sort(dates, Comparator.comparing(Date::getName));
Collections.reverse(dates);
dates.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
*/
Java 8 List.sort()
Java 8 List interface has sort() method that also uses Comparator
to induce the order.
dates.sort(Comparator.comparing(Date::getName));
dates.forEach(System.out::println);
/*
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
*/
For Descending order, let’s use Comparator.reversed() like this.
dates.sort(Comparator.comparing(Date::getName).reversed());
dates.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
*/
Java 8 Stream.sorted()
In case we don’t want to keep the order of the original ArrayList, we can return a new sorted ArrayList with sorted() method of Java 8 Stream interface with specified Comparator as input parameter.
ArrayList<Date> sortedDates = (ArrayList<Date>) dates
.stream().sorted(Comparator.comparing(Date::getName))
.collect(Collectors.toList());
sortedDates.forEach(System.out::println);
/*
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
*/
Then we can get a new ArrayList sorted by field for descending order with additional Comparator.reversed()
method.
ArrayList<Date> sortedDatesDescending = (ArrayList<Date>) dates
.stream().sorted(Comparator.comparing(Date::getName).reversed())
.collect(Collectors.toList());
sortedDatesDescending.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
*/
Sort ArrayList of Objects by multiple fields in Java
You can see that all of the results above show the sorted List just by name
field.
Think about the case you want to sort this ArrayList of Objects by multiple fields: name
first, then year
, then month
. How to do this?
Let’s use thenComparing() with a function that extracts a Comparable
sort key like this:
Comparator<Date> dateComparator = Comparator.comparing(Date::getName)
.thenComparing(Date::getYear)
.thenComparing(Date::getMonth);
Collections.sort()
For example, we sort the ArrayList<Date>
in Ascending order:
Collections.sort(dates, dateComparator);
dates.forEach(System.out::println);
/*
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
*/
And this is for Descending order:
Collections.sort(dates, dateComparator);
Collections.reverse(dates);
dates.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
*/
Java 8 List.sort()
Using this way, you can see that the code is clearer for reading.
Sort by Ascending
Comparator<Date> dateComparator = Comparator.comparing(Date::getName)
.thenComparing(Date::getYear)
.thenComparing(Date::getMonth);
dates.sort(dateComparator);
dates.forEach(System.out::println);
/*
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
*/
Sort by Descending with Comparator.reversed()
dates.sort(dateComparator.reversed());
dates.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
*/
Java 8 Stream.sorted()
The examples show you how to return new sorted ArrayList using sorted()
method of Stream
interface in Java 8.
Sort by Ascending
Comparator<Date> dateComparator = Comparator.comparing(Date::getName)
.thenComparing(Date::getYear)
.thenComparing(Date::getMonth);
ArrayList<Date> sortedDates = (ArrayList<Date>) dates
.stream().sorted(dateComparator)
.collect(Collectors.toList());
sortedDates.forEach(System.out::println);
/*
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
*/
Sort by Descending
ArrayList<Date> sortedDatesDescending = (ArrayList<Date>) dates
.stream().sorted(dateComparator.reversed())
.collect(Collectors.toList());
sortedDatesDescending.forEach(System.out::println);
/*
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
*/
Sort ArrayList of Objects with custom Comparator
Overview
We’re gonna follow these steps:
– Implement Comparator interface for the class we’re gonna use for handling sorting.
– Override compare(T o1, T o2)
method and:
- return zero if
o1
is equalo2
- a negative number if
o1
is less thano2
- a positive number if
o1
is greater thano2
– Use Collections.sort() method or Java 8 List.sort() to in-place sort the ArrayList, Java 8 Stream.sorted() to return a new sorted ArrayList of Objects without affecting the original List.
– For Descending order, just use additional Comparator.reversed() method.
Create Class for objects to be sorted
Date.java
package com.bezkoder.java.arraylist.sorting;
public class Date {
private String name;
private int year;
private int month;
public Date(String name, int year, int month) {
this.name = name;
this.year = year;
this.month = month;
}
// getters & setters
@Override
public String toString() {
return "Date [name=" + name + ", year=" + year + ", month=" + month + "]";
}
}
Create Class for handling sorting
This is the main part, CompareDates class overrides Comparator.compare() method.
DateComparator.java
package com.bezkoder.java.arraylist.sorting;
import java.util.Comparator;
public class DateComparator implements Comparator<Date> {
@Override
public int compare(Date o1, Date o2) {
int compareName = o1.getName().compareTo(o2.getName());
int compareYear = o1.getYear() - o2.getYear();
int compareMonth = o1.getMonth() - o2.getMonth();
if (compareName == 0) {
return ((compareYear == 0) ? compareMonth : compareYear);
} else {
return compareName;
}
}
}
3 ways Sorting using custom Comparator
This is the ArrayList of Date objects that will be sorted by Ascending & Descending order.
ArrayList<Date> dates = new ArrayList<>();
dates.add(new Date("DDD", 2020, 2));
dates.add(new Date("AAA", 2022, 11));
dates.add(new Date("ZZZ", 2020, 5));
dates.add(new Date("AAA", 2021, 8));
dates.add(new Date("AAA", 2021, 6));
dates.add(new Date("DDD", 2021, 2));
dates.add(new Date("ZZZ", 2020, 3));
Collections.sort()
System.out.println("--- ASC ---");
Collections.sort(dates, new DateComparator());
dates.forEach(System.out::println);
System.out.println("--- DESC ---");
Collections.sort(dates, new DateComparator());
Collections.reverse(dates);
dates.forEach(System.out::println);
Java 8 List.sort()
System.out.println("--- ASC ---");
dates.sort(new DateComparator());
dates.forEach(System.out::println);
System.out.println("--- DESC ---:");
dates.sort(new DateComparator().reversed());
dates.forEach(System.out::println);
Java 8 Stream.sorted()
System.out.println("--- ASC ---");
ArrayList<Date> sortedDates = (ArrayList<Date>) dates
.stream().sorted(new DateComparator())
.collect(Collectors.toList());
sortedDates.forEach(System.out::println);
System.out.println("--- DESC ---:");
ArrayList<Date> sortedDatesDescending = (ArrayList<Date>) dates
.stream().sorted(new DateComparator().reversed())
.collect(Collectors.toList());
sortedDatesDescending.forEach(System.out::println);
Each of method we use will print out the Result:
--- ASC ---
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
--- DESC ---
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
Sort ArrayList of Objects in Java using Comparable
Overview
Let’s follow these steps:
– Implement Comparable interface for the class of objects you want to sort.
– Override compareTo(T other)
method and:
- return zero if this
object
is equalother
- a negative number if the
object
is less thanother
- a positive number if it is greater than
other
– Use Collections.sort() method for sorting the ArrayList in-place, or Java 8 Stream.sorted() to return a new sorted ArrayList of Objects (the original List will not be modified).
– For Descending order, just pass Collections.reverseOrder() as input parameter to sorting method above.
Collections.reverseOrder()
helps us reverse the natural ordering of a Collection of objects that implement the Comparable
interface.
Create Comparable Class
Let’s create ComparableDate
class that implements Comparable
.
ComparableDate.java
package com.bezkoder.java.arraylist.sorting;
public class ComparableDate implements Comparable<ComparableDate> {
private String name;
private int year;
private int month;
public ComparableDate(String name, int year, int month) {
this.name = name;
this.year = year;
this.month = month;
}
// getters & setters
@Override
public String toString() {
return "Date [name=" + name + ", year=" + year + ", month=" + month + "]";
}
@Override
public int compareTo(ComparableDate other) {
int compareName = this.getName().compareTo(other.getName());
int compareYear = this.getYear() - other.getYear();
int compareMonth = this.getMonth() - other.getMonth();
if (compareName == 0) {
return ((compareYear == 0) ? compareMonth : compareYear);
} else {
return compareName;
}
}
}
2 ways Sorting using Comparable
Let’s initialize ArrayList of ComparableDate
objects that will be sorted by Ascending & Descending order.
ArrayList<ComparableDate> comparableDates = new ArrayList<>();
comparableDates.add(new ComparableDate("DDD", 2020, 2));
comparableDates.add(new ComparableDate("AAA", 2022, 11));
comparableDates.add(new ComparableDate("ZZZ", 2020, 5));
comparableDates.add(new ComparableDate("AAA", 2021, 8));
comparableDates.add(new ComparableDate("AAA", 2021, 6));
comparableDates.add(new ComparableDate("DDD", 2021, 2));
comparableDates.add(new ComparableDate("ZZZ", 2020, 3));
Collections.sort()
System.out.println("--- ASC ---");
Collections.sort(comparableDates);
comparableDates.forEach(System.out::println);
System.out.println("--- DESC ---:");
Collections.sort(comparableDates, Collections.reverseOrder());
comparableDates.forEach(System.out::println);
Java 8 Stream.sorted()
System.out.println("--- ASC ---");
ArrayList<ComparableDate> sortedDates = (ArrayList<ComparableDate>) comparableDates
.stream().sorted()
.collect(Collectors.toList());
sortedDates.forEach(System.out::println);
System.out.println("--- DESC ---:");
ArrayList<ComparableDate> sortedDatesDescending = (ArrayList<ComparableDate>) comparableDates
.stream()
.sorted(Collections.reverseOrder()).collect(Collectors.toList());
sortedDatesDescending.forEach(System.out::println);
The Result is the same for 2 methods:
--- ASC ---
Date [name=AAA, year=2021, month=6]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2022, month=11]
Date [name=DDD, year=2020, month=2]
Date [name=DDD, year=2021, month=2]
Date [name=ZZZ, year=2020, month=3]
Date [name=ZZZ, year=2020, month=5]
--- DESC ---:
Date [name=ZZZ, year=2020, month=5]
Date [name=ZZZ, year=2020, month=3]
Date [name=DDD, year=2021, month=2]
Date [name=DDD, year=2020, month=2]
Date [name=AAA, year=2022, month=11]
Date [name=AAA, year=2021, month=8]
Date [name=AAA, year=2021, month=6]
Conclusion
Today we’ve learned many ways to sort an ArrayList of Objects in Java, from simple to more complicated way. You’ve known how to sort by field and multiple fields, or by using Comparator/Comparable.
Happly Learning! See you again.