Stream terminal operations

This example will show various code snippets to demonstrate stream terminal operations. Terminal operations produces a non-stream, result such as primitive value, a collection or no value at all. Terminal operations are typically preceded by intermediate operations which return another Stream which allows operations to be connected in a form of a query.

forEach

The Stream.forEach method will perform an action for each element in the stream. It is a simplified inline way to write a for loop. Below we will iterate over each element and will call System.our.println.

@Test
public void terminal_operation_foreach () {

    Stream.of("Hello", "World").forEach(p -> System.out.println(p));
}

toArray

In similar examples, convert array to array list and convert collection to array, this snippet will convert a stream to an array by calling Stream.toArray

@Test
public void terminal_operation_toArray() {

    Object[] objects = Stream.of(1, 2).toArray();

    assertTrue(objects.length == 2);
}

reduce

Stream.reduce operations are commonly found in statistic operations such as long summary statistics and combine the stream elements into one using a BinaryOperator. In this snippet, we will find the sum of all elements in a stream.

@Test
public void terminal_operation_reduce() {

    int sum = IntStream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b);

    assertEquals(0, sum);
}

collect

The Stream.collect terminal operation will convert the stream into some other container such as a list. In the snippet below, we will convert a stream to a set. Other uses cases for the Stream.collect can be seen in convert a collection to a map, filter map by entries, stream group by, and joining strings.

@Test
public void terminal_operation_collect() {

    Set<String> stringSet = Stream.of("some", "one", "some", "one")
            .collect(Collectors.toSet());

    assertThat(stringSet, contains(
            "some", "one"));
    
    assertTrue(stringSet.size() == 2);
}

min

Finding the minimum of a stream is another statistics type operation which can be performed by calling Stream.min. In this snippet we create an IntStream which is a specialized stream for handling primitive int and call the min. Finding the minimum of a stream is similar to finding the minimum of an array or minimum of a list.

@Test
public void terminal_operation_min() {
    
    OptionalInt minimum = IntStream.of(1, 2, 3).min();

    assertEquals(1,  minimum.getAsInt());
}

max

Stream.max will find the maximum element of the stream according to a specified comparator. In the snippet below we will call Stream.mapToDouble which apply the given function Double::doubleValue to each element returning a DoubleStream. Finding the max element in a stream is similar to finding max value in a list and max value in an array.

@Test
public void terminal_operation_max() {

    OptionalDouble max = Stream.of(1d, 2d, 3d)
            .mapToDouble(Double::doubleValue).max();

    assertEquals(1, max.getAsDouble(), 0);
}

count

Stream.count will find the number of elements in the stream. Counting the number of elements in a stream has similarities to counting the occurrences in a list, counting non empty strings in a collection and count words in file.

@Test
public void terminal_operation_count() {

    long count = Stream.of("one").count();
    
    assertEquals(1, count);      
}

anymatch

Stream.anyMatch will find out whether at least one of the elements in the stream matches a given predicate. In this snippet, we will create a predicate from a lambda expression to check if the length of a string is greater than 5. Comparable examples can seen in guava iterables example and list contains any element.

@Test
public void terminal_operation_anymatch() {

    boolean lengthOver5 = Stream.of("two", "three", "eighteen").anyMatch(
            s -> s.length() > 5);

    assertTrue(lengthOver5);
}

allMatch

Who doesn't like cookies! Stream.allMatch will check every element in the stream and find out if it matches the predicate. In the snippet below we will create a predicate with a lambda expression to check that each element in the list contains the character sequence "Cookies". Other related examples include list contains all and guava iterables all.

@Test
public void terminal_operation_allmatch() {

    List<String> cookies = Lists.newArrayList("Peanut Butter Cookies",
            "Oatmeal-Raisin Cookies", "Basic Chocolate Chip Cookies");

    boolean containCookies = cookies.stream().allMatch(
            p -> p.contains("Cookies"));

    assertTrue(containCookies);
}

noneMatch

Just the opposite of Stream.anymatch, Stream.noneMatch will find if no elements in the stream match the specified predicate. In the snippet below, we will create a IntStream and then check each of the elements doesn't equal to 5. In addition to this snippet, the stream find and match example has a neat way of showing the noneMatch in relation to a hidden game object.

@Test
public void terminal_operation_nonematch() {

    boolean noElementEqualTo5 = IntStream.of(1, 2, 3)
            .noneMatch(p -> p == 5);

    assertTrue(noElementEqualTo5);
}

findFirst

Stream.findFirst will find the first element in the stream which is resembles the same behavior as getting the first element in a list.

@Test
public void terminal_operation_findfirst() {

    Optional<String> val = Stream.of("one", "two").findFirst();

    assertEquals("one", val);
}

findAny

Similar to finding any element in array, Stream.findAny will find any element in a given stream.

@Test
public void terminal_operation_findany() {

    Optional<String> val = Stream.of("one", "two").findAny();

    assertEquals("one", val.get());
}