180. Filtering the non-zero elements of a stream

In Chapter 8, Functional Style Programming Fundamentals and Design Patterns, in the Writing functional interfaces section, we defined a filter() method based on a functional interface named Predicate. The Java Stream API already has such a method, and the functional interface is called java.util.function.Predicate.

Let's assume that we have the following List of integers:

List<Integer> ints = Arrays.asList(1, 2, -4, 0, 2, 0, -1, 14, 0, -1);

Streaming this list and extracting only non-zero elements can be accomplished as follows:

List<Integer> result = ints.stream()
.filter(i -> i != 0)
.collect(Collectors.toList());

The resulting list will contain the following elements: 1, 2, -4, 2, -1, 14, -1

The following diagram shows how filter() works internally:

Notice that, for several common operations, the Java Stream API already provides out of the box intermediate operations. Hence, there is no need to provide a Predicate. Some of these operations are as follows:

  • distinct(): Removes duplicates from the stream
  • skip(n): Discards the first n elements
  • limit(s): Truncates the stream to be no longer than s in length
  • sorted(): Sorts the stream according to the natural order
  • sorted(Comparator<? super T> comparator): Sorts the stream according to the given Comparator

Let's add these operations and a filter() to an example. We will filter zeros, filter duplicates, skip 1 value, truncate the remaining stream to two elements, and sort them by their natural order:

List<Integer> result = ints.stream()
.filter(i -> i != 0)
.distinct()
.skip(1)
.limit(2)
.sorted()
.collect(Collectors.toList());

The resulting list will contain the following two elements: -4 and 2.

The following diagram shows how this stream pipeline works internally:

When the filter() operation needs a complex/compound or long condition, then it is advisable to extract it in an ancillary static method and rely on method references. Therefore, avoid something like this:

List<Integer> result = ints.stream()
.filter(value -> value > 0 && value < 10 && value % 2 == 0)
.collect(Collectors.toList());

You should prefer something like this (Numbers is the class containing the ancillary method):

List<Integer> result = ints.stream()
.filter(Numbers::evenBetween0And10)
.collect(Collectors.toList());

private static boolean evenBetween0And10(int value) {
return value > 0 && value < 10 && value % 2 == 0;
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.9.147