In one of the previous article, we discussed on how to sort list of objects on multiple field/parameters where we have coded/developed our own customized Comparator.
We will reuse the same example to sort on multiple fields using Java 8 Comparator in a more elegant way using different approaches.
1. Comparator interface :
- This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference
- A comparison function, which imposes a total ordering on some collection of objects
- Comparators can be passed to a sort method (such as
Collections.sort
orArrays.sort
) to allow precise control over the sort order
2. Multiple Sorting using Comparator :
- Using Java 8 Comparator, we are going to sort list of Customer objects on the basis of three attributes viz.; name, city and their age
- First, we are going to sort the list according to their name
- Second, if name of the 2/3 customers are same then we are going to sort on the basis of their city
- Third and finally, if customers name/city are same then we are going to sort on the basis of their age in ascending order
- We can achieve this target using different approaches namely,
1. using Lambda Expression
2. using Method Reference
3. Inline sorting using Comparator
4. Collection.sort() method
5. Arrays.sort() method - All the above mentioned approaches produces same result but the way they are implemented using Java 8 Comparator differs
Customer.java
package net.bench.resources.stream.sorting.multiple.fields;
public class Customer {
// member variables
String custName;
String custCity;
Integer custAge;
// 3-arg parameterized constructor
// getters & setters
// toString() method
}
2.1 using Lambda Expression :
- In this approach, we are going to define 3 different Comparators using Lambda Expression as shown below
- 1st Name Comparator :- (cust1, cust2) -> cust1.getCustName().compareTo(cust2.getCustName())
- 2nd City Comparator :- (cust1, cust2) -> cust1.getCustCity().compareTo(cust2.getCustCity())
- 3rd Age Comparator :- (cust1, cust2) -> cust1.getCustAge().compareTo(cust2.getCustAge())
- Finally, passing above comparators to sorted() method using thenComparing() method one-by-one
MultipleSortingUsingJava8Lambda.java
package net.bench.resources.stream.sorting.multiple.fields;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class MultipleSortingUsingJava8Lambda {
// customer list
private static List<Customer> getUnSortedCustomers() {
return Arrays.asList(
new Customer("Shalini", "Chennai", 60),
new Customer("Sneha", "Pune", 73),
new Customer("Simran", "Bangalore", 37),
new Customer("Trisha", "Hyderabad", 52),
new Customer("Shalini", "Chennai", 70),
new Customer("Abirami", "Bangalore", 48),
new Customer("Trisha", "Mangalore", 45),
new Customer("Sneha", "Pune", 62),
new Customer("Shalini", "Chennai", 50)
);
}
// main() method
public static void main(String[] args) {
// get customer list
List<Customer> unsortedCustomerList = getUnSortedCustomers();
System.out.println("Before Sorting: Customer list :- \n");
unsortedCustomerList.stream().forEach(System.out::println);
System.out.println("\n\nSorted Customer list on multiple fields"
+ " using Lambda Expression :- \n");
// 1. customer Name comparator
Comparator<Customer> nameComparatorLEx =
(cust1, cust2) -> cust1.getCustName().compareTo(cust2.getCustName());
// 2. customer City comparator
Comparator<Customer> cityComparatorLEx =
(cust1, cust2) -> cust1.getCustCity().compareTo(cust2.getCustCity());
// 3. customer Age comparator
Comparator<Customer> ageComparatorLEx =
(cust1, cust2) -> cust1.getCustAge().compareTo(cust2.getCustAge());
// sorting on multiple fields (3-level) using Lambda expression
List<Customer> sortedCustomerList = unsortedCustomerList
.stream()
.sorted(
nameComparatorLEx // 1st compare Name
.thenComparing(cityComparatorLEx) // then 2nd compare City
.thenComparing(ageComparatorLEx)) // then 3rd compare Age
.collect(Collectors.toList()); // collect sorted customers to new list
// print new list to console using forEach()
sortedCustomerList.stream().forEach(cust -> System.out.println(cust));
}
}
Output:
Before Sorting: Customer list :-
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Sorted Customer list on multiple fields using Lambda Expression :-
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
2.2 using Method reference :
- In this approach, we are going to define 3 different Comparators using Method Reference as shown below
- 1st Name Comparator :- Comparator.comparing(Customer::getCustName)
- 2nd City Comparator :- Comparator.comparing(Customer::getCustCity)
- 3rd Age Comparator :- Comparator.comparing(Customer::getCustAge)
- Finally, passing above comparators to sorted() method using thenComparing() method one-by-one
MultipleSortingUsingJava8MethodReference.java
package net.bench.resources.stream.sorting.multiple.fields;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class MultipleSortingUsingJava8MethodReference {
// customer list
private static List<Customer> getUnSortedCustomers() {
return Arrays.asList(
new Customer("Shalini", "Chennai", 60),
new Customer("Sneha", "Pune", 73),
new Customer("Simran", "Bangalore", 37),
new Customer("Trisha", "Hyderabad", 52),
new Customer("Shalini", "Chennai", 70),
new Customer("Abirami", "Bangalore", 48),
new Customer("Trisha", "Mangalore", 45),
new Customer("Sneha", "Pune", 62),
new Customer("Shalini", "Chennai", 50)
);
}
public static void main(String[] args) {
// get customer list
List<Customer> unsortedCustomerList = getUnSortedCustomers();
System.out.println("Before Sorting: Customer list :- \n");
unsortedCustomerList.stream().forEach(System.out::println);
System.out.println("\n\nSorted Customer list on multiple fields"
+ " using Method Reference :- \n");
// 1. customer Name comparator
Comparator<Customer> nameComparatorMRef = Comparator
.comparing(Customer::getCustName);
// 2. customer City comparator
Comparator<Customer> cityComparatorMRef = Comparator
.comparing(Customer::getCustCity);
// 3. customer Age comparator
Comparator<Customer> ageComparatorMRef = Comparator
.comparing(Customer::getCustAge);
// sorting on multiple fields (3-level) using Method Reference
List<Customer> sortedCustomerList = unsortedCustomerList
.stream()
.sorted(
nameComparatorMRef // 1st compare Name
.thenComparing(cityComparatorMRef) // then 2nd compare City
.thenComparing(ageComparatorMRef)) // then 3rd compare Age
.collect(Collectors.toList()); // collect sorted customers to new list
// print new list to console using forEach()
sortedCustomerList.stream().forEach(System.out::println);
}
}
Output:
Before Sorting: Customer list :-
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Sorted Customer list on multiple fields using Method Reference :-
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
2.3 Inline sorting using Comparator :
- In this approach, we are going to pass 3 Comparators to sorted() method using thenComparing() method one-by-one using Method Reference
CustomerSortingUsingJava8Comparing.java
package net.bench.resources.stream.sorting.multiple.fields;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class CustomerSortingUsingJava8Comparing {
// customer list
private static List<Customer> getUnSortedCustomers() {
return Arrays.asList(
new Customer("Shalini", "Chennai", 60),
new Customer("Sneha", "Pune", 73),
new Customer("Simran", "Bangalore", 37),
new Customer("Trisha", "Hyderabad", 52),
new Customer("Shalini", "Chennai", 70),
new Customer("Abirami", "Bangalore", 48),
new Customer("Trisha", "Mangalore", 45),
new Customer("Sneha", "Pune", 62),
new Customer("Shalini", "Chennai", 50)
);
}
// main() method
public static void main(String[] args) {
// get customer list
List<Customer> unsortedCustomerList = getUnSortedCustomers();
System.out.println("Before Sorting: Customer list :- \n");
unsortedCustomerList.stream().forEach(System.out::println);
System.out.println("\n\nSorted Customer list on multiple fields :- \n");
// inline - sorting on multiple fields
List<Customer> sortedCustomerList = unsortedCustomerList
.stream()
.sorted(
Comparator.comparing(Customer::getCustName) // 1st compare Name
.thenComparing(Customer::getCustCity) // then 2nd compare City
.thenComparing(Customer::getCustAge)) // then 3rd compare Age
.collect(Collectors.toList()); // collect sorted customers to new list
// print new list to console using forEach()
sortedCustomerList.stream().forEach(System.out::println);
}
}
Output:
Before Sorting: Customer list :-
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Sorted Customer list on multiple fields :-
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
2.4 Collections.sort() method :
- In this approach, we are going to define 3 Comparators namely nameComparator, cityComparator and ageComparator using Method Reference
- Finally, we are going to create another composition Comparator using thenComparing() method passing 3 comparators one-by-one
- Customer list and composition Comparator are passed as arguments to Collections.sort() method for multiple field sorting
MultipleSortingUsingCollectionsSortMethod.java
package net.bench.resources.stream.sorting.multiple.fields;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MultipleSortingUsingCollectionsSortMethod {
// customer list
private static List<Customer> getUnSortedCustomers() {
return Arrays.asList(
new Customer("Shalini", "Chennai", 60),
new Customer("Sneha", "Pune", 73),
new Customer("Simran", "Bangalore", 37),
new Customer("Trisha", "Hyderabad", 52),
new Customer("Shalini", "Chennai", 70),
new Customer("Abirami", "Bangalore", 48),
new Customer("Trisha", "Mangalore", 45),
new Customer("Sneha", "Pune", 62),
new Customer("Shalini", "Chennai", 50)
);
}
public static void main(String[] args) {
// get customer list
List<Customer> customerList = getUnSortedCustomers();
System.out.println("Before Sorting: Customer list :- \n");
customerList.stream().forEach(System.out::println);
System.out.println("\n\nSorting Customer list using Collection.sort() :- \n");
// 1. customer Name comparator
Comparator<Customer> nameComparator = Comparator
.comparing(Customer::getCustName);
// 2. customer City comparator
Comparator<Customer> cityComparator = Comparator
.comparing(Customer::getCustCity);
// 3. customer Age comparator
Comparator<Customer> ageComparator = Comparator
.comparing(Customer::getCustAge);
// 4. composition of above 3 Comparators
Comparator<Customer> multipleFieldComparator = nameComparator // 1st compare Name
.thenComparing(cityComparator) // then 2nd compare City
.thenComparing(ageComparator); // then 3rd compare Age
// sorting on multiple fields using composition Comparator
Collections.sort(customerList, multipleFieldComparator);
// print to console
customerList.forEach(System.out::println);
}
}
Output:
Before Sorting: Customer list :-
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Sorting Customer list using Collection.sort() :-
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
2.5 Arrays.sort() method :
- In this approach, we are going to define 3 Comparators namely nameComparator, cityComparator and ageComparator using Method Reference
- Finally, we are going to create another composition Comparator using thenComparing() method passing 3 comparators one-by-one
- Customer[] array and composition Comparator are passed as arguments to Arrays.sort() method for multiple field sorting
- Note: we can also print Arrays in the following manner Arrays.toString(customerArr) but result will be in one single line
MultipleSortingUsingArraysSortMethod.java
package net.bench.resources.stream.sorting.multiple.fields;
import java.util.Arrays;
import java.util.Comparator;
public class MultipleSortingUsingArraysSortMethod {
// customer list
private static Customer[] getUnSortedCustomers() {
return new Customer[] {
new Customer("Shalini", "Chennai", 60),
new Customer("Sneha", "Pune", 73),
new Customer("Simran", "Bangalore", 37),
new Customer("Trisha", "Hyderabad", 52),
new Customer("Shalini", "Chennai", 70),
new Customer("Abirami", "Bangalore", 48),
new Customer("Trisha", "Mangalore", 45),
new Customer("Sneha", "Pune", 62),
new Customer("Shalini", "Chennai", 50)
};
}
public static void main(String[] args) {
// get customer list
Customer[] customerArr = getUnSortedCustomers();
System.out.println("Before Sorting: Customer Array :- \n");
Arrays.stream(customerArr).forEach(System.out::println);
System.out.println("\n\nSorting Customer[] using Arrays.sort() :- \n");
// 1. customer Name comparator
Comparator<Customer> nameComparator = Comparator
.comparing(Customer::getCustName);
// 2. customer City comparator
Comparator<Customer> cityComparator = Comparator
.comparing(Customer::getCustCity);
// 3. customer Age comparator
Comparator<Customer> ageComparator = Comparator
.comparing(Customer::getCustAge);
// 4. composition of above 3 Comparators
Comparator<Customer> multipleFieldComparator = nameComparator // 1st compare Name
.thenComparing(cityComparator) // then 2nd compare City
.thenComparing(ageComparator); // then 3rd compare Age
// sorting on multiple fields using composition Comparator
Arrays.sort(customerArr, multipleFieldComparator);
// print to console
Arrays.stream(customerArr).forEach(System.out::println);
}
}
Output:
Before Sorting: Customer Array :-
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Sorting Customer[] using Arrays.sort() :-
Customer [custName=Abirami, custCity=Bangalore, custAge=48]
Customer [custName=Shalini, custCity=Chennai, custAge=50]
Customer [custName=Shalini, custCity=Chennai, custAge=60]
Customer [custName=Shalini, custCity=Chennai, custAge=70]
Customer [custName=Simran, custCity=Bangalore, custAge=37]
Customer [custName=Sneha, custCity=Pune, custAge=62]
Customer [custName=Sneha, custCity=Pune, custAge=73]
Customer [custName=Trisha, custCity=Hyderabad, custAge=52]
Customer [custName=Trisha, custCity=Mangalore, custAge=45]
Related Articles :
- Java – Sorting ArrayList using Comparable and Comparator
- Java – Sorting ArrayList in descending order
- Java – How to sort LinkedList using Collections.sort() method ?
- Java – How to sort Vector using Collections.sort() method ?
- Java – Sorting list of objects on multiple fields using Comparator
- Java – Sorting HashSet contents in ascending and descending order
- Java – How to Sort HashSet in 2 ways ?
- Java 8 – How to sort HashSet ?
- Java – How to sort LinkedHashSet contents ?
- Java – How to sort TreeSet in descending order using Comparator ?
- Java – Sorting Collection of String, StringBuffer and StringBuilder
- Java – Sorting ArrayList in descending order
- Java 8 – Sorting ArrayList using sort() method of List
- Java – How to Sort String List by its length in Ascending/Descending order ?
References :
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
- 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 !!