java-sort-arraylist-of-objects-feature-image

Java – Sort ArrayList of Objects

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


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 equal o2
  • a negative number if o1 is less than o2
  • a positive number if o1 is greater than o2

– 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 equal other
  • a negative number if the object is less than other
  • 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.

Further Reading

Leave a Reply

Your email address will not be published. Required fields are marked *