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 a
Comparable
sort key from a type T - Comparator used to compare the sort key from a type U
- Function that extracts a
- 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:
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#comparing-java.util.function.Function-java.util.Comparator-
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html
- https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
Happy Coding !!
Happy Learning !!