Java Stream termination

There were quite a few things I didn't understand about the Stream termination process added in Java 8, so I studied it.

Stream operations are performed in the order of Stream generation ⇒ intermediate processing ⇒ termination processing. Stream generation ⇒ Even if only intermediate processing is executed, it does not affect the original list etc. and there is no return value. If you want to do something, or if you want to get the result, you have to execute the termination process.

I think that I will increase it more if I feel like it, but this time I will list the ones that I picked up appropriately.

count It is easy to understand as it is, but it counts the number of Streams. It is usually used in combination with intermediate processing such as filter.

count


/**
 *Check Stream termination count
 */
@Test
public void count() {
    //As it is
    long count = IntStream.rangeClosed(1, 10).count();
    System.out.println(count); // ⇒ 10
    //Usually used in combination with intermediate processing
    long count2 = IntStream.rangeClosed(1, 10).filter(i -> i >  4).count();
    System.out.println(count2); // ⇒ 6
}

toArray The method name is the same, but Stream is converted to array format and returned. Two patterns with and without arguments are prepared for toArray, and if executed without arguments, they will be returned as an array of Objects. If there is an argument, the argument must specify a "generator" function that returns an array of integer size passed as an argument.

toArray


/**
 *Check Stream termination to Array
 */
@Test
public void toArray() {
    List<String> testList = new ArrayList<String> (Arrays.asList("ABC1", "ABD2", "DBC3", "CBC4"));

    //Since there is no argument, it is returned as an array of Object
    Object[] streamToArray= testList.stream().toArray();
    System.out.println(Arrays.toString(streamToArray)); // ⇒ [ABC1, ABD2, DBC3, CBC4]

    //If you specify the generator function that returns an array of String, the value will be set in the returned array and it will be returned.
    String[] streamToArrayFunc = testList.stream().toArray(String[]::new);
    System.out.println(Arrays.toString(streamToArrayFunc)); // ⇒ [ABC1, ABD2, DBC3, CBC4]

    // String[]::new is "i"->  new String[i]Is an abbreviation.
    String[] streamToArrayFunc2 = testList.stream().toArray(i ->  new String[i]);
    System.out.println(Arrays.toString(streamToArrayFunc2)); // ⇒ [ABC1, ABD2, DBC3, CBC4]

    //Of course, returning an array with a size other than the specified size will result in an error.
    try {
        String[] streamToArrayFunc3 = testList.stream().toArray(i ->  new String[i - 1]);
    } catch (IllegalStateException e) {
        System.out.println(e.getClass().getName()); // ⇒ java.lang.IllegalStateException
    }
}

max, min Extract the maximum and minimum values from the Stream. Specify Comparator as an argument. You can specify the function to be compared with compareTo as in the past, but it is recommended to use the function in Comparator like Java8 because it is easier to understand. The following example uses a function called comparingInt for the Comparator. This function takes each element as an argument, returns a numerical value, and calculates the minimum value based on the returned value.

MaxMin


/**
 *Stream termination processing max,Check min
 */
@Test
public void maxMin() {
    List<String> testList = new ArrayList<String> (Arrays.asList("ABC1", "ABD2", "DBC3", "CBC4"));

    Optional<String> streamMax = testList.stream().max((str1, str2) -> str1.substring(3, 4).compareTo(str2.substring(3,4)));
    System.out.println(streamMax); ⇒ Optional[CBC4]

    Optional<String> streamMin = testList.stream().min(Comparator.comparingInt(str -> Integer.parseInt(str.substring(3,  4))));
    System.out.println(streamMin); ⇒ Optional[ABC1]
}

reduce Performs a reduction operation on each element of Stream and returns the result. The value to be returned will be of the same type as the Stream element. What is reduction operation? I think there are many people who say that. In fact I was the same. Simply put, a reduction operation takes a series of values, such as an array, and returns a single summary result. This is the count, max, etc. that have come out so far. In addition, the following operations in Java can also be called reduction operations.

int sum = 0;
for (int i : new int[]{1, 5, 8}) {
    sum += i;
}

There are three types of reduce depending on the type of argument.

One parameter

sample


List<String> testList = new ArrayList<String> (Arrays.asList("ABC1", "ABD2", "DBC3", "CBC4"));

Optional<String>  reduceValue1 = testList.stream().reduce((result, element) -> {
    //result is the total so far
    //element is the current value
    return String.join("/", result, element);
});
System.out.println(reduceValue1); // ⇒ Optional[ABC1/ABD2/DBC3/CBC4]

If you have BinaryOperator as an argument, set a function that has two values as arguments. The value returned by this function last time is entered as the first argument. The second argument is the value of the Stream element. In this case, result = ABC1, element = ABD2 for the first time, result = ABC1 / ABD2, element = DBC3 for the second time.

Two parameters

sample


String reduceValue2 = testList.stream().reduce("FIRST", (result, element) -> {
    //result is the total so far
    //element is the current value
    return String.join("/", str1, str2);
});
System.out.println(reduceValue2); // ⇒ FIRST/ABC1/ABD2/DBC3/CBC4

It is almost the same as the case of one parameter, but here you can set the initial value in the first argument. The accumulator specified in the second argument processes the value specified in the first argument. I think that the return value is not Optimal because the value specified in the first argument is returned even if the list is empty.

3 parameters

sample


String reduceValue3 = testList.parallelStream().reduce("FIRST", (result, element) -> {
    //result is the total so far
    //element is the current value
    return String.join("/", result, element);
}, (result1, result2) -> {
    //result1 is the total so far
    //result2 is the current value
    return String.join("/", result1, result2);
});
System.out.println(reduceValue3); // ⇒ FIRST/ABC1-FIRST/ABD2-FIRST/DBC3-FIRST/CBC4

When there are three parameters, the first and second arguments are the same as when there are two parameters, only the third argument is different. The third argument is a function that is called only when executed in parallel, and the result of the second argument is combined and returned.

collect Performs variable reduction operations on each element of Stream. The reduction operation is as explained in reduce. So what is variable? Normal reduction operations return a single value. String or int. The variable reduction operation is to store and return values in what is called a variable container (Collection, StringBuilder, etc.). The difference between the reduction operation and the variable reduction operation is the difference between returning with a single value, returning with a variable container, and returning.

Return to the description of the collect function. There are two types of collect functions, one is to take Collector as an argument, and the other is to take three arguments: Supplier, accumulator, and combiner. First, when taking a Collector.

collect


/**
 *Stream termination processing Check collect Collector
 */
@Test
public void collect1() {
    List<String> testList = new ArrayList<String> (Arrays.asList("ABC1", "ABD2", "DBC3", "CBC4"));

    //Convert Stream to a list.
    List<String> list = testList.stream().map(s -> s.substring(0,  2)).collect(Collectors.toList());
    System.out.println(list); // ⇒ [AB, AB, DB, CB]

    //Map is returned using the value returned by the function specified by groupingBy as a key.
    Map<String, List<String>> groupingMap = testList.stream().collect(Collectors.groupingBy(s -> s.substring(0,1)));
    System.out.println(groupingMap); // ⇒ {A=[ABC1, ABD2], C=[CBC4], D=[DBC3]}
}

In this way, variable reduction can be achieved easily. Collectors has a lot of useful functions. Also, if I have time, I would like to introduce this as well.

Next, when taking three arguments, Supplier, accumulator, and combiner.

collect


/**
 *Check Stream termination collect
 */
@Test
public void collect2() {
    List<String> testList = new ArrayList<String> (Arrays.asList("ABC1", "ABD2", "DBC3", "CBC4"));
    Map<String, List<String>> groupingMap2 = testList.stream().collect(HashMap<String, List<String>>::new, (map, s) -> {
        String key = s.substring(0, 1);
        List<String> innerList = map.getOrDefault(key, new ArrayList<String>());
        innerList.add(s);
        map.put(key, innerList);
    }, (map1, map2) -> {});
    System.out.println(groupingMap2); // ⇒ {A=[ABC1, ABD2], C=[CBC4], D=[DBC3]}

    Map<String, List<String>> groupingMap3 = testList.parallelStream().collect(HashMap<String, List<String>>::new, (map, s) -> {
        String key = s.substring(0, 1);
        List<String> innerList = map.getOrDefault(key, new ArrayList<String>());
        innerList.add(s);
        map.put(key, innerList);
    }, (map1, map2) -> {});
    System.out.println(groupingMap3); // ⇒ {A=[ABC1]}The value is subject to change.

    Map<String, List<String>> groupingMap4 = testList.parallelStream().collect(HashMap<String, List<String>>::new, (map, s) -> {
        String key = s.substring(0, 1);
        List<String> innerList = map.getOrDefault(key, new ArrayList<String>());
        innerList.add(s);
        map.put(key, innerList);
    }, (map1, map2) -> {
        map2.forEach((key, list) -> {
            List<String> innerList = map1.getOrDefault(key, new ArrayList<String>());
            innerList.addAll(list);
            map1.put(key, innerList);
        });
    });
    System.out.println(groupingMap4); // ⇒ {A=[ABC1, ABD2], C=[CBC4], D=[DBC3]}
}

It returns the same value as the previous example using groupingBy. Each argument has the following meaning: Supplier: Define a function that returns a variable container to be returned by the collect function. accumulator: The container returned by Supplier is passed as the first argument, and each element of Stream is passed as the second argument. Set the value in the container returned by this function. combiner: If you do not perform parallel processing, you do not need to set anything. Defines the process to combine the values returned by the second argument when parallel processing is performed.

This is the end of the explanation of termination processing. Difficult to reduce and collect. For collect, I prefer to use Collector because it's easier. Please let me know if there are any mistakes.

Recommended Posts

Java Stream termination
[Java] Stream API --Stream termination processing
[JAVA] Stream type
Try Java 8 Stream
Java Stream API
Studying Java 8 (Stream)
[Java] Stream processing
Java 9 Optional :: stream
[Java] Stream API-Stream generation
[Java] Stream API / map
Java8 Stream API practice
Java8 Stream reduction operation
Java8 Stream Rough Summary
[Java11] Stream Summary -Advantages of Stream-
Java Stream API cheat sheet
Java Stream API in 5 minutes
Java8 stream, lambda expression summary
[Java] Stream API --Stream intermediate processing
Java Stream cannot be reused.
[Java] Introduction to Stream API
Java
[Java11] Stream Usage Summary -Basics-
Java application for beginners: stream
[Java] Stream API intermediate operation
[Java 8] Duplicate deletion (& duplicate check) with Stream
[Java] Stream (filter, map, forEach, reduce)
[java8] To understand the Stream API
About Lambda, Stream, LocalDate of Java8
[Introduction to Java] About Stream API
[Java] Element existence check with Stream
I tried using Java8 Stream API
Basic processing flow of java Stream
Java 8 ~ Stream API ~ to start now
Java array / list / stream mutual conversion list
Java8 list conversion with Stream map
Do you use Stream in Java?
Java learning (0)
Studying Java ―― 3
[Java] array
Java protected
[Java] Annotation
Java array
Studying Java ―― 9
Java scratch scratch
java (constructor)
[Java] ArrayDeque
Data processing using stream API from Java 8
java (override)
java (method)
Java Day 2018
Java string
java (array)
Java static
java beginner 4
Studying Java ―― 4
Java (set)
java shellsort
[Java] compareTo
Studying Java -5
Try using the Stream API in Java
java reflexes