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
SortingPrimitiveIntNumbers.java
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
SortingStringObjects.java
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
// getter and setters
// override toString() method
}
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 acc. 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 acc. 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 acc. 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
ReverseSortingPrimitiveIntNumbers.java
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.sorted() method
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.sorted() method
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
ReverseSortingStringObjects.java
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
.stream() // 2.1 get sequential stream
.sorted(Comparator.naturalOrder()) // 2.2 sorting alphabetical order
.collect(Collectors.toList()); // 2.3 collect to new list
// 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
.stream() // 3.1 get sequential stream
.sorted(Comparator.reverseOrder()) // 3.2 reverse sorting
.collect(Collectors.toList()); // 3.3 collect to new list
// pretty print to console
System.out.println("\n3. Reverse Sorting of String elements : \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 of String elements :
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:
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html
- https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
Happy Coding !!
Happy Learning !!