Java 8 – Sort a List with Stream sorted()
Learn to use Stream sorted() method to sort the elements in a List by their natural order and reverse order. We can also apply for custom orders on the elements using the provided Comparator.
The Stream interface provides two methods for sorting the Stream elements.
- sorted() – Provides the default sorting
- sorted(Comparator) – Sorting based on the provided comparator.
- sorted() is a stateful intermediate operation that returns a new Stream.
- It returns a stream consisting of the elements of this stream, sorted according to the natural order.
- If the elements of this stream are not Comparable , a java.lang.ClassCastException may be thrown when the terminal operation is executed.
- For ordered streams, the sort is stable.
- For unordered streams, no stability guarantees are made.
1.2. Stream sorted(comparator)
Stream sorted(Comparator comparator)
- This is a stateful intermediate operation that returns a new stream.
- It returns a stream consisting of the elements of this stream, sorted according to the provided Comparator..
- For ordered streams, the sort is stable.
- For unordered streams, no stability guarantees are made.
Example 1: Sorting in Natural Order
In the given Java example, we are sorting a List of integers in the natural order and printing them into the standard output.
List list = Arrays.asList(2, 4, 1, 3, 7, 5, 9, 6, 8); List sortedList = list.stream() .sorted() .collect(Collectors.toList()); System.out.println(sortedList);
Example 2: Reverse Ordering
In the given Java example, we are sorting a stream of integers in reverse order using a Comparator.reverseOrder() and printing them into the standard output.
List list = Arrays.asList(2, 4, 1, 3, 7, 5, 9, 6, 8); List sortedList = list.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println(sortedList);
Example 3: Custom Ordering using Comparator
In the given Java example, we are sorting a stream of integers using a custom Comparator.
List list = Arrays.asList(2, 4, 1, 3, 7, 5, 9, 6, 8); Comparator reverseComparator = new Comparator() < @Override public int compare(Integer i1, Integer i2) < return i2.compareTo(i1); >>; List sortedList = list.stream() .sorted(reverseComparator) .collect(Collectors.toList()); System.out.println(sortedList);
Example 4: Sorting using Lambda Expressions
Java example to sort a stream of integers in reverse order using lambda expression to specify the comparison logic.
We are rewriting the previous Comparator logic with an inline lambda expression.
List list = Arrays.asList(2, 4, 1, 3, 7, 5, 9, 6, 8); List sortedList = list.stream() .sorted( (i1, i2) -> i2.compareTo(i1) ) .collect(Collectors.toList()); System.out.println(sortedList);
Drop me your questions related to Stream sorted() example in Java Stream API.
Reverse elements of stream java 8
In this episode we will show how to reverse the element position while maintaining order in a java 8 stream.
Detailed Video Notes
Java 8 introduced stream which is a sequence of elements supporting sequential and parallel aggregate operations. In addition it helped introduce a functional programming style to java. It is a possible that a stream has unordered elements so this tutorial is not to be confused with sorting a stream in reverse order. Let’s find out how to flip the elements in the stream while maintaining order.
Setup
Generating a java project from a maven archetype quick start we will update the project to use java 8 and add the dependencies of junit and guava.
junit junit 4.11 test com.google.guava guava 18.0
Reverse order and print
For our first java example let us create a Stream of Strings then collect the elements into a LinkedList . Since a LinkedList is a double-linked data structure we are able to navigate in either direction, forward or reverse. Calling DescendingIterator allows us to iterate over the elements in reverse sequential order. We can output the elements in the Stream by passing the System.out::println consumer to the forEachRemaining method.
Lets run our test and examine the output of the elements in reversed order.
@Test public void reverse_stream_print() Stream.of("One", "Two", "Three", "Four") .collect(Collectors.toCollection(LinkedList::new)) .descendingIterator().forEachRemaining(System.out::println); >
Proving the sort
Just to prove that the order is different when you sort a stream, lets write a quick test method and sort the elements in reversed order. Again we will build a stream calling sorted, an intermediate stream operation, passing in Collections.reverseOrder() will sort the stream in reverse alphabetical order. Using the foreach we can print the elements of the stream.
Lets run our test and examine the output of the elements in reversed order.
@Test public void sorting_reverse() Stream.of("One", "Two", "Three", "Four") .sorted(Collections.reverseOrder()) .forEach(System.out::println); >
Reverse order convert to ArrayList
Next you might be thinking, how do I convert an Iterator to a collection? This is a two step process first we must reverse the order and then transform the Iterator into a list. Using the same snippet above and assigning reversedStream to the Iterator returned we can create a new stream by using StreamSupport and Spliterators . Finally we can transform stream tolist using Collectors utility.
Lets run our test and examine the output of converting Iterator to list using stream functions.
@Test public void reverse_stream_collect_to_list() IteratorString> reversedStream = Stream .of("One", "Two", "Three", "Four") .collect(Collectors.toCollection(LinkedList::new)) .descendingIterator(); ListString> listReversedOrder = StreamSupport.stream( Spliterators.spliteratorUnknownSize(reversedStream, Spliterator.ORDERED), false).collect( Collectors.String> toList()); System.out.println(listReversedOrder); >
Iterable to Arraylist using guava
If the previous snippet is to painful and you already have guava on you classpath, you could convert Iterable to arraylist using guava’s list utility.
@Test public void iterator_to_list_guava() IteratorString> reversedStream = Stream .of("One", "Two", "Three", "Four") .collect(Collectors.toCollection(LinkedList::new)) .descendingIterator(); ListString> reversedList = Lists.newArrayList(reversedStream); System.out.println(reversedList); >
Reverse order numeric stream
If you are working with numbers the following technique could be applied to IntStream, DoubleStream or LongStream. Note: this technique was not tested and verified for performance.
Creating a static method that accepts an IntStream we will create an array from a stream and then use the same techniques we find in reversing elements of an array in java.
Let’s run our example to see the output.
public static IntStream reverseOrderStream(IntStream intStream) int[] tempArray = intStream.toArray(); return IntStream.range(1, tempArray.length + 1).boxed() .mapToInt(i -> tempArray[tempArray.length - i]); > @Test public void intstream_reverse_order() reverseOrderStream(IntStream.of(1, 4, 5, 6, 7)).forEach( System.out::println); >
I hope this showed the difference in reversing the order of elements of a stream vs sorting in reverse order while providing a few techniques to convert an Iterable to a collection.
Thanks for joining in today’s level up, have a great day!
Reverse elements of stream java 8 posted by Justin Musgrove on 23 February 2015
Tagged: java, java-tutorial, and java8
All the code on this page is available on github: View the source
How to Sort a Stream in Java
Learn to sort streams of numbers, strings and custom types in ascending (natural order) and descending orders (reverse order) in Java.
1. Basics of Sorting the Streams
The Stream interface provides the sorted() method that returns a stream consisting of the elements of a given stream, sorted according to the natural order. It is an overloaded method:
- Stream sorted() : sorted according to natural order.
- Stream sorted(comparator) : sorted according to the provided Comparator.
Note that both methods are intermediate operations so we still need to call a terminal operation to trigger the sorting.
Stream unsortedStream; //Default Ordering List sortedList = unsortedStream.sorted() .collect(Collectors.toList()); //Order by First Name List sortedList = unsortedStream.sorted(Person::firstName) .collect(Collectors.toList());
For demonstration purposes, we are using the custom class Person . This class has only three fields: id, first name and last name.
By default, two persons are considered equal if their id is equal.
import java.util.Objects; public class Person implements Comparable < private Integer id; private String fname; private String lname; //Constructor, Setters and Getters are hidden for brevity @Override public int compareTo(Person p) < return this.getId().compareTo(p.getId()); >>
By default, the sorted() method uses the Comparable.compareTo() method implemented by the Person class.
As Person class compares the instances using the value of id field, so when we sort the stream of Person instances – we get the instances sorted by id. The default sorting is in the natural order.
Stream personStream = getPersonStream(); // Ascending Order personStream.sorted() .forEach(System.out::println);
Person [id=1, fname=Lokesh, lname=Gupta] Person [id=2, fname=Lokesh, lname=Gupta] Person [id=3, fname=Brian, lname=Clooney] Person [id=4, fname=Brian, lname=Clooney] Person [id=5, fname=Lokesh, lname=Gupta]
The same is true for reverse sorting as well. we can sort the Person instances in reverse order by passing the reverse comparator obtained from Comparator.reverseOrder() method into the sorted() method.
Stream personStream = getPersonStream(); // Reverse Order personStream.sorted(Comparator.reverseOrder()) .forEach(System.out::println);
Person [id=6, fname=Alex, lname=Kolen] Person [id=5, fname=Lokesh, lname=Gupta] Person [id=4, fname=Brian, lname=Clooney] Person [id=3, fname=Brian, lname=Clooney] Person [id=2, fname=Lokesh, lname=Gupta] Person [id=1, fname=Lokesh, lname=Gupta]
What if we want to sort the Person instances by their first name. The default sort does not support it, so we need to create our custom comparator.
import java.util.Comparator; import com.howtodoinjava.core.streams.Person; public class FirstNameSorter implements Comparator < @Override public int compare(Person p1, Person p2) < if(p1.getFname() == null || p2.getFname() == null) < throw new IllegalArgumentException("Unnamed Person found in the system"); >return p1.getFname().compareToIgnoreCase(p2.getFname()); > >
Now pass the FirstNameSorter instance to the sorted() method. This time, sorting will use the compare() method written in FirstNameSorter.
List sortedList = personStream.sorted(new FirstNameSorter()) .collect(Collectors.toList()); sortedList.forEach(System.out::println);
Person [id=6, fname=Alex, lname=Kolen] Person [id=4, fname=Brian, lname=Clooney] Person [id=3, fname=Brian, lname=Clooney] Person [id=1, fname=Lokesh, lname=Gupta] Person [id=5, fname=Lokesh, lname=Gupta] Person [id=2, fname=Lokesh, lname=Gupta]
Similarly, to sort the instances by the first name in reverse order, we can reverse any comparator using its reverse() method.
List reverseSortedList = personStream.sorted( new FirstNameSorter().reversed() ) .collect(Collectors.toList()); reverseSortedList.forEach(System.out::println);
2.3. Class cannot be cast to class java.lang.Comparable
Please note that if our custom class Person does not implement the Comparable interface then we will get the ClassCastException in runtime while doing the natural sorting.
Exception in thread "main" java.lang.ClassCastException: class com.howtodoinjava.core.streams.sort.Person cannot be cast to class java.lang.Comparable (com.howtodoinjava.core.streams.sort.Person is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap') at java.base/java.util.Comparators $NaturalOrderComparator.compare(Comparators.java:47) at java.base/java.util.TimSort. countRunAndMakeAscending(TimSort.java:355) at java.base/java.util.TimSort. sort(TimSort.java:220) at java.base/java.util.Arrays. sort(Arrays.java:1307)
3. Sorting Stream of Numbers
Java programs to sort a stream of numbers using Stream.sorted() method.
import java.util.stream.Stream; public class Main < public static void main(String[] args) < StreamnumStream = Stream.of(1,3,5,4,2); numStream.sorted() .forEach(System.out::println); > >
To sort in reverse order, use Comparator.reverseOrder() in sorted() method.
import java.util.Comparator; import java.util.stream.Stream; public class Main < public static void main(String[] args) < StreamnumStream = Stream.of(1,3,5,4,2); numStream.sorted( Comparator.reverseOrder() ) .forEach(System.out::println); > >
4. Sorting Stream of Strings
Java programs to sort a stream of strings using Stream.sorted() method in ascending and descending order.
Stream wordStream = Stream.of("A","C","E","B","D"); wordStream.sorted() //ascending .forEach(System.out::println); wordStream.sorted( Comparator.reverseOrder() ) //descending .forEach(System.out::println);