Reverse elements of a Stream in Java
This post will discuss how to reverse elements of a stream in Java. In other words, create a new stream that iterates the elements of the specified stream in reverse order.
1. Using List
Since streams in Java doesn’t store any elements, the idea is to collect the stream elements into a list, inplace reverse the list using Collections.reverse()
, and convert the reversed list back to a stream. We can use the Collectors.toList()
method to create an intermediate list and Collectors.collectingAndThen()
method to adapt the Collectors.toList()
collector to produce a list in reverse order. Here’s an example of how we can achieve this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; class Main { public static <T> Collector<T, ?, Stream<T>> reverse() { return Collectors.collectingAndThen(Collectors.toList(), list -> { Collections.reverse(list); return list.stream(); }); } public static void main(String[] args) { List<Integer> lists = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = lists.stream(); stream.collect(reverse()).forEach(System.out::println); // 5, 4, 3, 2, 1 } } |
2. Using LinkedList
A LinkedList class in Java is implemented as a stack and supports insertion at the front. We can take advantage of this fact and collects the stream elements into a LinkedList, then returns a descending iterator over the list. The iterator can be used to traverse the elements in reverse order. Here is a sample code that demonstrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; class Main { public static <T> Iterator<T> reverse(Stream<T> stream) { return stream.collect(Collectors.toCollection(LinkedList::new)) .descendingIterator(); } public static void main(String[] args) { List<Integer> lists = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = lists.stream(); Iterator<Integer> reverse = reverse(stream); reverse.forEachRemaining(System.out::println); // 5, 4, 3, 2, 1 } } |
3. Using ArrayDeque
The Collector
interface provides static factory method Collector.of()
that can be used to construct collectors. The idea is to create a custom collector that accumulates the stream elements into an ArrayDeque, adding each element to the front of the deque. Then we can convert the ArrayDeque
to a Stream
by calling its stream()
method. Here is an example of how the code might look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.ArrayDeque; import java.util.Arrays; import java.util.List; import java.util.stream.Collector; import java.util.stream.Stream; class Main { public static <T> Stream<T> reverse(Stream<T> stream) { return stream.collect(Collector.of(() -> new ArrayDeque<T>(), ArrayDeque::addFirst, (a, b) -> { b.addAll(a); return b; })).stream(); } public static void main(String[] args) { List<Integer> lists = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = lists.stream(); reverse(stream).forEach(System.out::println); // 5, 4, 3, 2, 1 } } |
Another option is to use ArrayList instead of an ArrayDeque
, but since it adds elements at the end, it is slower and not recommended. We can use it like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collector; import java.util.stream.Stream; class Main { public static <T> Collector<T, List<T>, List<T>> reverse() { return Collector.of(ArrayList::new, List::add, (a, b) -> { a.addAll(b); return a; }, list -> { Collections.reverse(list); return list; }); } public static void main(String[] args) { List<Integer> lists = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = lists.stream(); stream.collect(reverse()).forEach(System.out::println); // 5, 4, 3, 2, 1 } } |
That’s all about reversing elements of a Stream in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)