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

[0:21]

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.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
</dependency>

Reverse order and print

[0:29]

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);

}

Output

Four
Three
Two
One

Proving the sort

[0:57]

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);

}

Output

Two
Three
One
Four

Reverse order convert to ArrayList

[1:20]

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() {

    Iterator<String> reversedStream = Stream
            .of("One", "Two", "Three", "Four")
            .collect(Collectors.toCollection(LinkedList::new))
            .descendingIterator();

    List<String> listReversedOrder = StreamSupport.stream(
            Spliterators.spliteratorUnknownSize(reversedStream,
                    Spliterator.ORDERED), false).collect(
            Collectors.<String> toList());

    System.out.println(listReversedOrder);
}

Output

[Four, Three, Two, One]

Iterable to Arraylist using guava

[1:56]

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() {

    Iterator<String> reversedStream = Stream
            .of("One", "Two", "Three", "Four")
            .collect(Collectors.toCollection(LinkedList::new))
            .descendingIterator();

    List<String> reversedList = Lists.newArrayList(reversedStream);

    System.out.println(reversedList);
}

Output

[Four, Three, Two, One]

Reverse order numeric stream

[2:5]

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);
}

Output

7
6
5
4
1

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!