Java 8 – Sorting List of primitive, String & Custom Objects

In this article, we will discuss how to sort list of primitive int, String & Custom Objects in Java 1.8 version.

1. Stream sorted() method

  • This Stream method is an intermediate operation which sorts elements present in the stream according to natural order
  • If elements present in the stream aren’t Comparable then java.lang.ClassCastException is thrown when final terminal operation is executed
  • For ordered streams, the sort is stable
  • For unordered streams, no stability guarantees are made.
  • Stream’s sorted() method is stateful
  • Another intermediate operation can be applied to returned stream for example filter(), map(), distinct() methods can be applied after sorted() operation
  • Method signature :- Stream<T> sorted()

1.1 Sorting List of Primitive int

  • Here, there are first 10 natural numbers in random order
  • We are sorting these integer numbers in natural order (or ascending order) using Java 8 Stream’s sorted() method
  • Lambda expression – finally, printing sorted numbers using Java 8 Stream’s forEach() method to console
package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortingPrimitiveIntNumbers {

	public static void main(String[] args) {

		// 1. List - 1st 10 natural numbers in random order
		List<Integer> numbers = Arrays.asList(7, 3, 10, 1, 8, 4, 6, 5, 2, 9);
		
		// pretty print numbers in random order
		System.out.println("1. Original List of Integer numbers in random order :\n");
		numbers.forEach(num -> System.out.print(num + "\t"));

		// 2. sorting using Stream's sorted() method
		List<Integer> sortedIntNumbers = numbers // original source elements
				.stream() // 2.1 get sequential stream
				.sorted() // 2.2 sort acc. to natural order 
				.collect(Collectors.toList()); // 2.3 collect to new list after sorting

		// pretty printing to console
		System.out.println("\n\n\n2. Sorted integer numbers in Ascending order : \n");
		sortedIntNumbers.forEach(num -> System.out.print(num + "\t"));
	}
}

Output:

1. Original List of Integer numbers in random order :

7	3	10	1	8	4	6	5	2	9


2. Sorted integer numbers in Ascending order : 

1	2	3	4	5	6	7	8	9	10

1.2 Sorting List of String Objects

  • Here, 1st we are defining few String elements in List
  • Then we are sorting these String elements in natural order (or alphabetical order) using Java 8 Stream’s sorted() method
  • Method reference – finally, printing sorted String elements using Java 8 Stream’s forEach() method to console
package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortingStringObjects {

	public static void main(String[] args) {

		// 1. List of String elements
		List<String> companies = Arrays.asList(
				"Infosys",
				"Capgemini",
				"Hexaware",
				"LTI",
				"Accenture"
				);

		// pretty print to console
		System.out.println("1. Original List of String :\n");
		companies.forEach(System.out::println);

		// 2. sorting using Stream's sorted() method
		List<String> sortedCompanyNames = companies // original source elements
				.stream() // 2.1 get sequential stream
				.sorted() // 2.2 sorting alphabetical order of String elements
				.collect(Collectors.toList()); // 2.3 collect to new list after sorting

		// pretty print to console
		System.out.println("\n2. Sorted Company Names in Alphabetical order : \n");
		sortedCompanyNames.forEach(System.out::println);
	}
}

Output:

1. Original List of String :

Infosys
Capgemini
Hexaware
LTI
Accenture

2. Sorted Company Names in Alphabetical order : 

Accenture
Capgemini
Hexaware
Infosys
LTI

2. Stream sorted(Comparator) method

  • This Stream method is an intermediate operation which sorts elements present in the stream according to Comparator provided
  • This Comparator logic can be either in natural order or reverse order depending upon our business requirement
  • For ordered streams, the sort is stable
  • For unordered streams, no stability guarantees are made.
  • Stream’s sorted(Comparator) method is stateful
  • Method signature :- Stream<T> sorted(Comparator<? super T> comparator)

2.1 Sorting List of Custom Objects

  • Here, we are adding Player objects with 4 attributes (Id, Name, Average, Rank) to List object
  • Example-1 : sorting Player objects according to Id in natural order using Comparator p1, p2 -> p1.getId() – p2.getId(); and printing to console using lambda expression
  • Example-2 : sorting Player objects according to Name in alphabetical order using Comparator p1, p2 -> p1.getName() .compare(p2.getName()); and printing to console using lambda expression
  • Example-3 : sorting Player objects according to Rank in natural order using Comparator p1, p2 -> p1.getRank() – p2.getRank(); and printing to console using lambda expression

Player.java

class Player {

	// private member variables
	private int id;
	private String name;
	private double average;
	private int rank;

	// public 4-arg parameterized constructor
	public Player(int id, String name, double average, int rank) {
		super();
		this.id = id;
		this.name = name;
		this.average = average;
		this.rank = rank;
	}

	// getter and setters
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getAverage() {
		return average;
	}
	public void setAverage(double average) {
		this.average = average;
	}
	public int getRank() {
		return rank;
	}
	public void setRank(int rank) {
		this.rank = rank;
	}

	// override toString() method
	@Override
	public String toString() {
		return "Player [id=" + id 
				+ ", name=" + name 
				+ ", average=" + average 
				+ ", rank=" + rank 
				+ "]";
	}
}

SortingCustomObjects.java

package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortingCustomObjects {

	public static void main(String[] args) {

		// 1. List of Student objects
		List<Player> fab5IndianOrder = Arrays.asList(
				new Player(1, "Dravid", 88.55, 2),
				new Player(2, "Sehwag", 55.65, 5),
				new Player(3, "Laxman", 77.75, 3),
				new Player(4, "Sachin", 99.25, 1),
				new Player(5, "Sourav", 66.15, 4)
				);

		// 1. unsorted players by any attributes - original list
		System.out.println("1. List of unsorted Players in orginal list :\n");
		fab5IndianOrder.forEach(System.out::println);

		// 2. Natural sorting acc. to Player's Id
		List<Player> sortedById = fab5IndianOrder // original source
				.stream() // 2.1 get sequential stream
				.sorted((p1, p2) -> p1.getId() - p2.getId()) // 2.2 sort by Id
				.collect(Collectors.toList()); // 2.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n2. Players sorted acc. to Natural order of Id :\n");
		sortedById.forEach(playerById -> System.out.println(playerById));

		// 3. Natural sorting acc. to Player's Name
		List<Player> sortedByName = fab5IndianOrder // original source
				.stream() // 3.1 get sequential stream
				.sorted((p1, p2) -> p1.getName().compareTo(p2.getName())) // 3.2 sort by Name
				.collect(Collectors.toList()); // 3.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n3. Players sorted acc. to Alphabetical order of Name :\n");
		sortedByName.forEach(playerByName -> System.out.println(playerByName));

		// 4. Natural sorting acc. to Player's Rank
		List<Player> sortedByRank = fab5IndianOrder // original source
				.stream() // 4.1 get sequential stream
				.sorted((p1, p2) -> Integer.compare(p1.getRank(), p2.getRank()))// 4.2 Rank sort
				.collect(Collectors.toList()); // 4.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n4. Players sorted acc. to Natural order of Rank :\n");
		sortedByRank.forEach(playerByRank -> System.out.println(playerByRank));
	}
}

Output:

1. List of unsorted Players in orginal list :

Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=5, name=Sourav, average=66.15, rank=4]


2. Players sorted according to Natural order of Id :

Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=5, name=Sourav, average=66.15, rank=4]


3. Players sorted according to Alphabetical order of Name :

Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=5, name=Sourav, average=66.15, rank=4]


4. Players sorted according to Natural order of Rank :

Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=2, name=Sehwag, average=55.65, rank=5]

3. Reverse sorting

  • This section covers example for sorting primitive int, String & Custom Objects in reverse order by passing Comparator
  • We can build logic around Comparator to sort elements in either natural order or reverse order
  • Comparator.naturalOrder() helps to sort in natural order, if the objects are Comparable otherwise java.lang.ClassCastException is thrown
  • Comparator.reverseOrder() helps to sort in reverse order, if the objects are Comparable otherwise java.lang.ClassCastException is thrown

3.1 Reverse sorting List of Primitive int

  • This example has list of integer numbers
  • we are sorting in natural & reverse order using Comparator.naturalOrder() i.e.; in ascending order & Comparator.reverseOrder() i.e.; in descending order respectively
  • Lambda expression – finally, printing sorted Student objects using Java 8 Stream’s forEach() method to console
package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class ReverseSortingPrimitiveIntNumbers {

	public static void main(String[] args) {

		// 1. List - 10 numbers in random order
		List<Integer> numbers = Arrays.asList(35, 15, 10, 5, 50, 20, 45, 30, 25, 40);

		// pretty print numbers in random order
		System.out.println("1. Original List of Integer numbers in Random order :\n");
		numbers.forEach(randomOrderNumber -> System.out.print(randomOrderNumber + "\t"));

		// 2. Ascending sorting using Stream's sorted() method by Comparator.naturalOrder()
		List<Integer> sortedIntNumbers = numbers // original source elements
				.stream() // 2.1 get sequential stream
				.sorted(Comparator.naturalOrder()) // 2.2 sort acc. to natural order 
				.collect(Collectors.toList()); // 2.3 collect to new list after sorting

		// pretty printing to console
		System.out.println("\n\n\n2. Natural sorting - Ascending order : \n");
		sortedIntNumbers.forEach(
				ascendingOrderNumber -> System.out.print(ascendingOrderNumber + "\t"));

		// 3. Descending sorting using Stream's sorted() method by Comparator.reverseOrder()
		List<Integer> reverseNumbers = numbers // original source elements
				.stream() // 3.1 get sequential stream
				.sorted(Comparator.reverseOrder()) // 3.2 reverse sorting
				.collect(Collectors.toList()); // 3.3 collect to new list after sorting

		// pretty printing to console
		System.out.println("\n\n\n3. Reverse sorting - Descending order : \n");
		reverseNumbers.forEach(
				descendingOrderNumber -> System.out.print(descendingOrderNumber + "\t"));
	}
}

Output:

1. Original List of Integer numbers in Random order :

35	15	10	5	50	20	45	30	25	40


2. Natural sorting - Ascending order : 

5	10	15	20	25	30	35	40	45	50


3. Reverse sorting - Descending order : 

50	45	40	35	30	25	20	15	10	5

3.2 Reverse sorting List of String elements

  • This example has list of String elements
  • we are sorting in natural & reverse order using Comparator.naturalOrder() i.e.; in alphabetical order and Comparator.reverseOrder() respectively
  • Lambda expression – finally, printing sorted Student objects using Java 8 Stream’s forEach() method to console
package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class ReverseSortingStringObjects {

	public static void main(String[] args) {

		// 1. List of String elements
		List<String> companies = Arrays.asList(
				"Infosys",
				"Capgemini",
				"Hexaware",
				"LTI",
				"Accenture"
				);

		// pretty print to console
		System.out.println("1. Original List of String :\n");
		companies.forEach(System.out::println);

		// 2. natural sorting using Stream's sorted() method
		List<String> sortedCompanyNames = companies // original source elements
				.stream() // 2.1 get sequential stream
				.sorted(Comparator.naturalOrder()) // 2.2 sorting alphabetical order of String
				.collect(Collectors.toList()); // 2.3 collect to new list after sorting

		// pretty print to console
		System.out.println("\n2. Sorted by Company Names in Alphabetical order : \n");
		sortedCompanyNames.forEach(System.out::println);

		// 3. reverse sorting using Stream's sorted() method
		List<String> reverseSorting = companies // original source elements
				.stream() // 3.1 get sequential stream
				.sorted(Comparator.reverseOrder()) // 3.2 reverse sorting
				.collect(Collectors.toList()); // 3.3 collect to new list after reverse sorting

		// pretty print to console
		System.out.println("\n3. Reverse Sorting : \n");
		reverseSorting.forEach(System.out::println);
	}
}

Output:

1. Original List of String :

Infosys
Capgemini
Hexaware
LTI
Accenture

2. Sorted by Company Names in Alphabetical order : 

Accenture
Capgemini
Hexaware
Infosys
LTI

3. Reverse Sorting : 

LTI
Infosys
Hexaware
Capgemini
Accenture

3.3 Reverse sorting List of Custom Objects

  • This example has list of Student objects
  • We are sorting Student objects based on all 4 attributes Id, Name, Rank & Average in reverse order
  • Reverse Id sorting – (p1, p2) -> p2.getId() – p1.getId();
  • Reverse Name sorting – (p1, p2) -> p2.getName().compareTo(p1.getName());
  • Reverse Rank sorting – (p1, p2) -> Integer.compare(p2.getRank(), p1.getRank());
  • Reverse Average sorting – (p1, p2) -> Double.compare(p2.getAverage(), p1.getAverage());
  • Lambda expression – finally, printing sorted Student objects using Java 8 Stream’s forEach() method to console

ReverseSortingCustomObjects.java

package net.bench.resources.stream.sorted.example;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ReverseSortingCustomObjects {

	public static void main(String[] args) {

		// 1. List of Student objects
		List<Player> fab5IndianOrder = Arrays.asList(
				new Player(4, "Sachin", 99.25, 1),
				new Player(1, "Dravid", 88.55, 2),
				new Player(2, "Sehwag", 55.65, 5),
				new Player(5, "Sourav", 66.15, 4),
				new Player(3, "Laxman", 77.75, 3)
				);

		// 1. unsorted players by any attributes - original list
		System.out.println("1. UNSORTED Players in orginal list :\n");
		fab5IndianOrder.forEach(System.out::println);

		// 2. REVERSE sorting acc. to Player's Id
		List<Player> sortedById = fab5IndianOrder // original source
				.stream() // 2.1 get sequential stream
				.sorted((p1, p2) -> p2.getId() - p1.getId()) // 2.2 Id sort
				.collect(Collectors.toList()); // 2.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n2. REVERSE sorting of Players by Id :\n");
		sortedById.forEach(playerById -> System.out.println(playerById));

		// 3. REVERSE sorting acc. to Player's Name
		List<Player> sortedByName = fab5IndianOrder // original source
				.stream() // 3.1 get sequential stream
				.sorted(
						(p1, p2) -> p2.getName().compareTo(p1.getName()) // 3.2 Name sort
						) 
				.collect(Collectors.toList()); // 3.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n3. REVERSE sorting of Players by Name :\n");
		sortedByName.forEach(playerByName -> System.out.println(playerByName));

		// 4. REVERSE sorting acc. to Player's Rank
		List<Player> sortedByRank = fab5IndianOrder // original source
				.stream() // 4.1 get sequential stream
				.sorted(
						(p1, p2) -> Integer.compare(p2.getRank(), p1.getRank()) // 4.2 Rank sort
						) 
				.collect(Collectors.toList()); // 4.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n4. REVERSE sorting of Players by Rank :\n");
		sortedByRank.forEach(playerByRank -> System.out.println(playerByRank));

		// 5. REVERSE sorting acc. to Player's Average
		List<Player> sortedByAverage = fab5IndianOrder // original source
				.stream() // 5.1 get sequential stream
				.sorted(
						(p1, p2) -> Double.compare(p2.getAverage(), p1.getAverage())
						) // 5.2 Average sort
				.collect(Collectors.toList()); // 5.3 collect to new List

		// pretty print to console using lambda expression
		System.out.println("\n\n5. REVERSE sorting of Players by Average :\n");
		sortedByAverage.forEach(playerByRank -> System.out.println(playerByRank));
	}
}

Output:

1. UNSORTED Players in orginal list :

Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=3, name=Laxman, average=77.75, rank=3]


2. REVERSE sorting of Players by Id :

Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=1, name=Dravid, average=88.55, rank=2]


3. REVERSE sorting of Players by Name :

Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=1, name=Dravid, average=88.55, rank=2]


4. REVERSE sorting of Players by Rank :

Player [id=2, name=Sehwag, average=55.65, rank=5]
Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=4, name=Sachin, average=99.25, rank=1]


5. REVERSE sorting of Players by Average :

Player [id=4, name=Sachin, average=99.25, rank=1]
Player [id=1, name=Dravid, average=88.55, rank=2]
Player [id=3, name=Laxman, average=77.75, rank=3]
Player [id=5, name=Sourav, average=66.15, rank=4]
Player [id=2, name=Sehwag, average=55.65, rank=5]

References:

Happy Coding !!
Happy Learning !!

Java 8 - Stream forEachOrdered method