← Back to Core Java Course | Chapter 11: Collections | Lesson 17 of 17

Java List Sorting

Sorting a list puts its items in order, like lining up kids by height. You can use the natural order or write your own rule for what comes first.
Syntax
java
Collections.sort(list);
list.sort(Comparator.comparing(Type::getField));

Sorting with Collections.sort()

The static method Collections.sort(list) sorts a List in place using each element's natural ordering, which requires the elements to implement Comparable.

It has been part of Java since the original Collections Framework and is still common in code written before Java 8.

Example: Sorting with Collections.sort()

java
import java.util.Collections;
import java.util.ArrayList;
public class Main {
	public static void main(String[] args) {
		ArrayList<Integer> nums = new ArrayList<>(java.util.List.of(3, 1, 2));
		Collections.sort(nums); // natural ordering, requires Comparable
		System.out.println(nums);
	}
}

Sorting with List.sort()

Since Java 8, every List has its own instance method list.sort(comparator), which is often preferred over Collections.sort() because it reads more naturally and lets you pass null to fall back to natural ordering.

Both methods sort the list in place rather than returning a new sorted list.

Example: Sorting with List.sort()

java
import java.util.ArrayList;
public class Main {
	public static void main(String[] args) {
		ArrayList<Integer> nums = new ArrayList<>(java.util.List.of(3, 1, 2));
		nums.sort(null); // null falls back to natural ordering
		System.out.println(nums);
	}
}

Natural Ordering via Comparable

A class defines its own default sort order by implementing Comparable<T> and its compareTo() method, returning negative, zero, or positive to indicate less-than, equal-to, or greater-than.

Built-in types like String and Integer already implement Comparable, which is why lists of them sort correctly with no extra setup.

Example: Natural Ordering via Comparable

java
// Define the class Person
class Person implements Comparable<Person> {
	int age;
	Person(int age) { this.age = age; }
	public int compareTo(Person other) {
		// Send this.age - other.age back to the caller
		return this.age - other.age;
	}
}
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		java.util.ArrayList<Person> people = new java.util.ArrayList<>();
		people.add(new Person(30));
		people.add(new Person(20));
		java.util.Collections.sort(people);
		// Print a line to the console
		System.out.println(people.get(0).age);
	}
}

Custom Ordering via Comparator Lambda

When you need a sort order different from the natural one, or you're sorting a class you can't modify, pass a Comparator instead — a lambda like list.sort((a, b) -> a.getAge() - b.getAge()) sorts by a different field entirely.

Unlike Comparable, a class can have many different comparators without changing its own code.

Example: Custom Ordering via Comparator Lambda

java
// Import java.util.ArrayList so it can be used by its short name
import java.util.ArrayList;
// Define the class Person
class Person {
	int age;
	Person(int age) { this.age = age; }
}
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new ArrayList object and store it in people
		ArrayList<Person> people = new ArrayList<>();
		people.add(new Person(30));
		people.add(new Person(20));
		people.sort((a, b) -> a.age - b.age);
		// Print a line to the console
		System.out.println(people.get(0).age);
	}
}

Sorting by Multiple Keys

The Comparator.comparing() and .thenComparing() methods let you build a multi-level sort, for example sorting people by last name and using first name only as a tiebreaker when last names match.

This reads clearly left to right and avoids writing a long manual if/else chain inside a compareTo() or lambda body.

Example: Sorting by Multiple Keys

java
// Import java.util.ArrayList so it can be used by its short name
import java.util.ArrayList;
// Import java.util.Comparator so it can be used by its short name
import java.util.Comparator;
// Define the class Person
class Person {
	String lastName, firstName;
	Person(String lastName, String firstName) {
		this.lastName = lastName;
		this.firstName = firstName;
	}
}
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new ArrayList object and store it in people
		ArrayList<Person> people = new ArrayList<>();
		people.add(new Person("Smith", "Bob"));
		people.add(new Person("Smith", "Alice"));
		people.sort(Comparator.comparing((Person p) -> p.lastName)
				.thenComparing(p -> p.firstName));
		// Print a line to the console
		System.out.println(people.get(0).firstName);
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Sorting with a comparator that subtracts values, such as a - b, which can overflow; use Integer.compare(a, b).
  2. Using Collections.sort() on an immutable list, which throws UnsupportedOperationException.
  3. Forgetting to implement Comparable for custom objects without a comparator.
Chapter Summary
  • The Collections framework provides List, Set, and Map interfaces with implementations such as ArrayList, LinkedList, HashMap, TreeMap, HashSet, and TreeSet.
  • Linked and ordered variants such as LinkedHashMap and LinkedHashSet keep a predictable order.
  • Stack, Queue, Iterator, the Collections class, and list sorting round out working with data structures.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.