Explain Codes LogoExplain Codes Logo

Sort ArrayList of custom Objects by property

java
sorting
comparator
lambda
Anton ShumikhinbyAnton Shumikhin·Nov 1, 2024
TLDR

Quickly sort an ArrayList of CustomObjects using Java 8's Comparator.comparing:

yourArrayList.sort(Comparator.comparing(CustomObject::getProperty));

For pre-Java 8, here is a tailor-made Comparator:

Collections.sort(yourArrayList, new Comparator<CustomObject>() { public int compare(CustomObject o1, CustomObject o2) { // returns int, not a boolean; however tempting it might be to return a boolean return o1.getProperty().compareTo(o2.getProperty()); } });

By default, the sort is ascending. For a descending sort, tag on .reversed() with Java 8, or swap o1 and o2 for an old school flip.

Unveiling Comparator

A Comparator's compare method yields an int. The returned value is positive if the first object is greater, zero if identical, and negative if smaller.

When Strings decide to become sensitive

We sometimes need case-insensitive sort especially with Strings. Here is the magic trick:

yourArrayList.sort(Comparator.comparing(CustomObject::getStringProperty, String.CASE_INSENSITIVE_ORDER)); // when Strings are too sensitive, sorting employs case insensitive order

Mastering the art of juggling conditions

To chain multiple sorting conditions, here's your tool:

yourArrayList.sort(Comparator.comparing(CustomObject::getPrimaryKey) .thenComparing(CustomObject::getSecondaryKey)); // Comparable says, "If you're too similar, let's go to plan B"

Watch your step

It's easy to trip over not returning the correct numbers from compare. It ruins your sorting experience. Always triple-check that your custom Comparator respects the contract: negative integer, zero, or a positive integer. You could call it the sorting community's secret handshake.

Streamlining with advanced sorting tech

The stream team

In Java 8 onwards, the Streams API accelerates the sorting process:

List<CustomObject> sortedList = yourArrayList.stream() .sorted(Comparator.comparing(CustomObject::getProperty)) .collect(Collectors.toList()); // when your ArrayList decides to get a stream makeover

Welcoming null values with open arms

When your property may be null, Comparator.nullsLast or Comparator.nullsFirst become your best friends to dodge NullPointerException:

yourArrayList.sort(Comparator.comparing(CustomObject::getProperty, Comparator.nullsLast(Comparator.naturalOrder()))); // null values finishing up the race with a lil walk!

The complex date sorting bash

For complex sorting logic on dates or other complicated requirements, curate a specialized Comparator:

Comparator<CustomObject> byDate = (o1, o2) -> o1.getComplexProperty().compareTo(o2.getComplexProperty()); yourArrayList.sort(byDate); // when dates decide to play hard to get

Full auto mode: Sorting sans Comparator (using Comparable)

If your CustomObject class implements Comparable, sorting is a leisurely stroll:

Collections.sort(yourArrayList); // when your CustomObject shakes hands with Comparable

This demands CustomObject to have an internal definition of compareTo, living up to Comparable's contract—interfacing for comparing objects of the same class directly.

Unstable sorting

Ensure your sorting logic is as deterministic as the rise of the sun, particularly with complex data types and comparisons. A non-consistent Comparator is like a ticking time bomb.

Sneaky equals & compareTo

If your custom object enjoys overriding equals, it’s generally a good idea to override compareTo as well. Mismatches between equals and compareTo can lead to strange results, especially with sorted collections like TreeSet.

Don’t drown in lambda expressions

While lambda expressions are as concise as a tweet, overusing them, especially with complex logic, might hide the idea under the carpet. Strike a balance between conciseness and readability, preferring method references or separate Comparator classes where it fits.