
Java streams 16. Filtering, Skipping, Sorting
We have completed the overview of Stream factory methods in the previous post and now turn to intermediate operations (see the Stream operations overview in Java streams 14. Stream factory methods and operations).
An intermediate operation returns a Stream object that emits the same or modified value(s) of the same or different type than the stream source. In this installment, we will discuss operations that do not change either element value or type. They just do not allow some elements to propagate downstream (filtering and skipping) or rearrange the elements in a different order (sorting).
The other three groups of intermediate operations are peeking using peek() reviewed in the previous installment, mapping using map(), and generating another stream using flatMap(). The last two we will discuss in the upcoming installments.
Filtering
This group includes operations that remove duplicate elements and select for further processing only those elements that pass certain criteria:
- Stream<T> distinct(). Compares stream elements using method Object.equals(Object) and skips the duplicates.
- Stream<T> filter(Predicate<T> predicate). Allows flowing downstream only those elements that result in true when processed by the provided Predicate function.
- default Stream<T> dropWhile(Predicate<T> predicate). Skips those first elements of the stream that result in true when processed by the provided Predicate function
- default Stream<T> takeWhile(Predicate<T> predicate). Allows only those first elements of the stream to be processed that result in true when processed by the provided Predicate function
For example:
Stream.of("2", "4", "3", "4", "2")
.distinct()
.forEach(System.out::print); //prints: 243Stream.of("2", "4", "3", "4", "2")
.filter(s -> Objects.equals(s, "2"))
.forEach(System.out::print); //prints: 22Stream.of("2", "4", "3", "4", "2")
.dropWhile(s -> Integer.valueOf(s) < 3)
.forEach(System.out::print); //prints: 4342Stream.of("2", "4", "3", "4", "2")
.takeWhile(s -> Integer.valueOf(s) < 3)
.forEach(System.out::print); //prints: 2
Please, notice that the last two operations have default implementation in the Stream interface. It means that the objects that implement the Stream interface do not need to implement these two methods. They inherit the implementation from the interface automatically. But when they do provide their own implementation of these two methods, the default implementation in the interface gets overwritten.
Skipping
This group includes operations that skip some of the elements, thus not allowing them to flow downstream. It is similar to filtering, except there is no function used as a criterion for skipping:
- Stream<T> skip(long n). Ignores the first n stream elements emitted by the Stream object.
- Stream<T> limit(long n). Allows only the first n stream elements emitted by the Stream object to flow downstream.
For example:
Stream.of("2", "4", "3", "4", "2")
.skip(3)
.forEach(System.out::print); //prints: 42Stream.of("2", "4", "3", "4", "2")
.limit(3)
.forEach(System.out::print); //prints: 243
Sorting
The following two intermediate operations sort the stream elements in default or specified order:
- Stream<T> sorted(). Sorts the stream elements in the natural order (according to
their implementation of the Comparable interface). - Stream<T> sorted(Comparator<T> comparator). Sorts the stream elements in the
order according to the provided Comparator<T> object.
For example:
Stream.of("2", "4", "3", "4", "2")
.sorted().forEach(System.out::print); //prints: 22344Stream.of("2", "4", "3", "4", "2")
.sorted(Comparator.reverseOrder())
.forEach(System.out::print); //prints: 44322
Please, notice that these operations can be applied only to a finite stream because they cannot be finished until all the elements are emitted. Naturally, these operations create a lot of overhead and slow down the stream processing. It would be wise to use them only for finite small-size streams.
In the next post, we will talk about the intermediate operation map() that transforms each of the emitted elements by applying to it a specified function.
See other posts on Java 8 streams and posts on other topics on www.nicksamoylov.com