Java 8 – Comparator.comparing() method for custom/reverse sorting

In this article, we will discuss how to sort list of Objects on the basis of any one parameter/field using Java 8 Comparator’s static method comparing() which accepts 2-arguments for custom/reverse sorting

Comparator.comparing() is the overloaded method where 1st variant accepts only-one argument and 2nd variant accepts 2-arguments

Already in the previous article we have discussed along with various examples for the 1st overloaded method, check Comparator.comparing() method for natural-order sorting

Here, we are going to discuss 2nd overloaded method which helps in customized sorting or reverse-order sorting of numbers or reverse-order alphabetical sorting of String elements

1. Comparator.comparing() method :

  • This static method accepts 2 arguments
    • Function that extracts Comparable sort key from a type T
    • Comparator used to compare the sort key from a type U
  • Returns a Comparator<T> that compares by that sort key
  • The returned comparator is serializable if the specified function is also serializable
  • Method signature :-
    • static <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator)
  • Where
    • T is the type of element to be compared
    • U is the type of sort key
    • keyExtractor is the function used to extract the sort key
    • keyComparator is the Comparator used to compare the sort key
  • Exception :- Throws NullPointerException, if the argument is null
  • Check Java doc

2. Comparator.comparing() examples :

  • Product class is defined with 4 attributes namely id, name, quantity and their price
  • Along with 4 attributes, 4-arguments parameterized constructor, getters/setters and toString() method is defined – removed for brevity

Product.java

package net.bench.resources.comparator.comparing.custom;

public class Product {

	// member variables
	private int id;
	private String name;
	private long quantity;
	private double price;

	// 4-arg parameterized constructor

	// getters and setters

	// toString() method
}

2.1 Sort Product list in reverse alphabetical order of its name

  • A list contains Product information for 5 as per insertion-order
  • Sorting :- we are going to sort the Product list in reverse alphabetial order of its name using Stream‘s sorted() method

SortProductListByNameInReverseOrder.java

package net.bench.resources.comparator.comparing.custom;

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

public class SortProductListByNameInReverseOrder {

	// List of Products
	private static List<Product> getProductList() {

		return Arrays.asList(
				new Product(101, "Wheat", 1089L, 36.89),
				new Product(102, "Rice", 502L, 58.19),
				new Product(103, "Lentils", 803L, 102.45),
				new Product(104, "Oil", 208L, 164.75),
				new Product(105, "Vegetables", 303L, 45.50)
				);
	}

	// main() method
	public static void main(String[] args) {

		// 1. get Product list
		List<Product> products = getProductList();


		// 1.1 print to console
		System.out.println("Product list as per Insertion-order :-\n");
		products.forEach(System.out::println); // iterating/printing



		// 2. sorting Product list in alphabetical order by its Name
		System.out.println("\n\nSorted Product list by"
				+ " REVERSE alphabetical order of Name :-\n");


		// 2.1 sorting/iterating/printing
		products
		.stream() // 1. get sequential stream
		.sorted(
				Comparator.comparing(
						Product::getName, // name sorting
						(str1, str2) -> str2.compareTo(str1) // reverse
						)
				)
		.forEach(System.out::println); // 3. iterate/printing
	}
}

Output:

Product list as per Insertion-order :-

Product [id=101, name=Wheat, quantity=1089, price=36.89]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=105, name=Vegetables, quantity=303, price=45.5]


Sorted Product list by REVERSE alphabetical order of Name :-

Product [id=101, name=Wheat, quantity=1089, price=36.89]
Product [id=105, name=Vegetables, quantity=303, price=45.5]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=103, name=Lentils, quantity=803, price=102.45]

2.2 Sort Product list in descending-order of Product Id

  • A list contains Product information for 5 as per insertion-order
  • Sorting :- we are going to sort the Product list in the descending order of Product Id using Stream‘s sorted() method

SortProductListByIdInReverseOrder .java

package net.bench.resources.comparator.comparing.custom;

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

public class SortProductListByIdInReverseOrder {

	// List of Products
	private static List<Product> getProductList() {

		return Arrays.asList(

				new Product(102, "Rice", 502L, 58.19),
				new Product(104, "Oil", 208L, 164.75),
				new Product(103, "Lentils", 803L, 102.45),
				new Product(105, "Vegetables", 303L, 45.50),
				new Product(101, "Wheat", 1089L, 36.89)
				);
	}

	// main() method
	public static void main(String[] args) {

		// 1. get Product list
		List<Product> products = getProductList();


		// 1.1 print to console
		System.out.println("Product list as per Insertion-order :-\n");
		products.forEach(System.out::println); // iterating/printing



		// 2. sorting Product list in ascending-order by its Id
		System.out.println("\n\nSorted Product list in descending-order of Id :-\n");


		// 2.1 sorting/iterating/printing
		products
		.stream() // 1. get sequential stream
		.sorted(
				Comparator.comparing(
						Product::getId, // Id sorting
						(int1, int2) -> int2-int1 // reverse
						)
				)
		.forEach(System.out::println); // 3. iterate/printing
	}
}

Output:

Product list as per Insertion-order :-

Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=105, name=Vegetables, quantity=303, price=45.5]
Product [id=101, name=Wheat, quantity=1089, price=36.89]


Sorted Product list in descending-order of Id :-

Product [id=105, name=Vegetables, quantity=303, price=45.5]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=101, name=Wheat, quantity=1089, price=36.89]

2.3 Sort Product list in descending-order of its quantity

  • A list contains Product information for 5 as per insertion-order
  • Sorting :- we are going to sort the Product list in the descending order of its quantity using Collections.sort() method passing reverse Comparator as 2nd argument and original list as 1st argument

SortProductListByQuantityInReverseOrder.java

package net.bench.resources.comparator.comparing.custom;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortProductListByQuantityInReverseOrder {

	// List of Products
	private static List<Product> getProductList() {

		return Arrays.asList(
				new Product(101, "Wheat", 1089L, 36.89),
				new Product(102, "Rice", 502L, 58.19),
				new Product(103, "Lentils", 803L, 102.45),
				new Product(104, "Oil", 208L, 164.75),
				new Product(105, "Vegetables", 303L, 45.50)
				);
	}

	// main() method
	public static void main(String[] args) {

		// 1. get Product list
		List<Product> productList = getProductList();


		// 1.1 print to console
		System.out.println("Product list as per Insertion-order :-\n");
		productList.forEach(System.out::println); // iterating/printing



		// 2. sorting Product list in ascending-order by its Quantity
		System.out.println("\n\nSorted Product list"
				+ " in descending-order of Quantity :-\n");


		// 2.1 sorting using Collections.sort() & Comparator
		Collections.sort(
				productList,  // original list
				Comparator.comparing(
						Product::getQuantity, // quantity sorting
						(lng1, lng2) -> Long.compare(lng2, lng1) // reverse
						)
				);


		// 2.2 iterate & printing
		productList.forEach(System.out::println); // iterating/printing
	}
}

Output:

Product list as per Insertion-order :-

Product [id=101, name=Wheat, quantity=1089, price=36.89]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=105, name=Vegetables, quantity=303, price=45.5]


Sorted Product list in descending-order of Quantity :-

Product [id=101, name=Wheat, quantity=1089, price=36.89]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=105, name=Vegetables, quantity=303, price=45.5]
Product [id=104, name=Oil, quantity=208, price=164.75]

2.4 Sort Product list in decreasing order of its price

  • A list contains Product information for 5 as per insertion-order
  • Sorting :- we are going to sort the Product list on the basis of decreasing price using Collections.sort() method passing reverse Comparator as 2nd argument and original list as 1st argument

SortProductListByPriceInReverseOrder.java

package net.bench.resources.comparator.comparing.custom;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortProductListByPriceInReverseOrder {

	// List of Products
	private static List<Product> getProductList() {

		return Arrays.asList(
				new Product(101, "Wheat", 1089L, 36.89),
				new Product(102, "Rice", 502L, 58.19),
				new Product(103, "Lentils", 803L, 102.45),
				new Product(104, "Oil", 208L, 164.75),
				new Product(105, "Vegetables", 303L, 45.50)
				);
	}

	// main() method
	public static void main(String[] args) {

		// 1. get Product list
		List<Product> productList = getProductList();


		// 1.1 print to console
		System.out.println("Product list as per Insertion-order :-\n");
		productList.forEach(System.out::println); // iterating/printing



		// 2. sorting Product list in increasing-order of price
		System.out.println("\n\nSorted Product list in decreasing-order of price :- \n");


		// 2.1 sorting using Collections.sort() & Comparator
		Collections.sort(
				productList,  // original list
				Comparator.comparing(
						Product::getPrice, // price sorting
						(dbl1, dbl2) -> Double.compare(dbl2, dbl1) // reverse
						)
				);


		// 2.2 iterate & printing
		productList.forEach(System.out::println); // iterating/printing
	}
}

Output:

Product list as per Insertion-order :-

Product [id=101, name=Wheat, quantity=1089, price=36.89]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=105, name=Vegetables, quantity=303, price=45.5]


Sorted Product list in decreasing-order of price :- 

Product [id=104, name=Oil, quantity=208, price=164.75]
Product [id=103, name=Lentils, quantity=803, price=102.45]
Product [id=102, name=Rice, quantity=502, price=58.19]
Product [id=105, name=Vegetables, quantity=303, price=45.5]
Product [id=101, name=Wheat, quantity=1089, price=36.89]

2.5 Throws NullPointerException if argument is NULL

  • If the input argument to Comparator.comparing() method is null then it throws NullPointerException as shown in the below illustration
  • Check How to sort List and Arrays with null values to handle list with null values while sorting

SortProductListWithNullPresent.java

package net.bench.resources.comparator.comparing.custom;

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

public class SortProductListWithNullPresent {

	// List of Products
	private static List<Product> getProductList() {

		return Arrays.asList(

				new Product(102, "Rice", 502L, 58.19),
				new Product(104, "Oil", 208L, 164.75),
				new Product(103, "Lentils", 803L, 102.45),
				new Product(105, "Vegetables", 303L, 45.50),
				new Product(101, "Wheat", 1089L, 36.89)
				);
	}

	public static void main(String[] args) {

		// 1. get Product list
		List<Product> products = getProductList();


		// 2. sorting Product list in ascending-order by its Id
		System.out.println("Exception - Sorted Product list with Null value :-\n");


		// 3. sorting/iterating/printing
		products
		.stream() // 1. get sequential stream
		.sorted(Comparator.comparing(null)) // 2. null
		.forEach(System.out::println); // 3. iterate/printing
	}
}

Output:

Exception - Sorted Product list with Null value :-

Exception in thread "main" java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Comparator.comparing(Comparator.java:467)
	at net.bench.resources.comparator.comparing.custom.SortProductListWithNullPresent
.main(SortProductListWithNullPresent.java:35)

3. Sorting String elements ignoring cases :

  • In below illustration, we are sorting String elements in alphabetical order ignoring cases

SortStringElementsIgnoringCases.java

package net.bench.resources.comparator.comparing.custom;

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

public class SortStringElementsIgnoringCases {

	public static void main(String[] args) {

		// 1. list of Strings
		List<String> names = Arrays.asList(
				"rafael",
				"messi",
				"argus",
				"zen",
				"Martin",
				"Roger",
				"Ben"
				);


		// 1.1 original String elements - insertion-order
		System.out.println("Original String elemetns"
				+ " as per Insertion-order :- \n");
		names.forEach(System.out::println);



		// 2. String comparator ignoring cases
		Comparator<String> stringComparator = Comparator
				.comparing(
						String::valueOf, // name comparison
						String.CASE_INSENSITIVE_ORDER // ignore cases
						);


		// 2.1 print to console
		System.out.println("\n\nSorted String list"
				+ " in alphabetical-order ignoring cases :- \n");


		// 2.2 sorting/iterate/printing
		names
		.stream()
		.sorted(stringComparator)
		.forEach(System.out::println);
	}
}

Output:

Original String elemetns as per Insertion-order :- 

rafael
messi
argus
zen
Martin
Roger
Ben


Sorted String list in alphabetical-order ignoring cases :- 

argus
Ben
Martin
messi
rafael
Roger
zen

References:

Happy Coding !!
Happy Learning !!

Java 8 – Comparator.comparingInt() method
Java 8 – Comparator.comparing() method