Java8 Stream detailed explanation and end operation method usage example (3)

         The end operation refers to the operation that ends the processing of the Stream and triggers the execution of the Stream. The following are some commonly used end operation methods. The end operation traverses the data source and is therefore evaluated early.

Detailed explanation of Java8 Stream and examples of using intermediate operation methods (1)
Detailed explanation of Java8
 

  1. forEach(Consumer<T> action): Performs the specified action on each element in the stream.
  2. toArray(): Convert the elements in the stream into an array.
  3. reduce(T identity, BinaryOperator<T> accumulator): Aggregates the elements in the stream using the specified accumulator.
  4. collect(Collector<T,A,R> collector): Collect the elements in the stream into a container.
  5. min(Comparator<T> comparator): Returns the smallest element in the stream.
  6. max(Comparator<T> comparator): Returns the largest element in the stream.
  7. count(): Returns the number of elements in the stream.
  8. anyMatch(Predicate<T> predicate): Determine whether any element in the stream matches the specified condition.
  9. allMatch(Predicate<T> predicate): Determine whether all elements in the stream match the specified condition.
  10. noneMatch(Predicate<T> predicate): Determine whether any element in the stream matches the specified condition.
  11. findFirst(): Returns the first element in the stream.
  12. findAny(): returns any element in the stream.

Stream end operation method detailed example

 forEach(Consumer<? super T> action)

forEach()method is Streama final action method in the class that receives a Consumerfunction as an argument to perform the specified action on each element in the stream. forEach()The method traverses the entire stream and performs the specified operation on each element, and the order of operations is performed in the order of the stream.

For example, suppose there is a list containing multiple strings, and now each string needs to be converted into lowercase letters and output, you can use forEach()the method to achieve:

List<String> strList = Arrays.asList("Java", "Stream", "API");
strList.stream()
       .map(String::toLowerCase)
       .forEach(System.out::println);

In the above code, first create one from the string list Stream, then execute String::toLowerCasethe method on each string, that is, convert the string to lowercase letters, and finally forEach()execute the operation on each element through the method System.out::println, that is, output the element to the console.

Note that since forEach()the method is a final action method, it cannot return any value. If you need to convert the elements in the stream to another object such as collection or array, you can use collect()the method. At the same time, since forEach()the method is a terminal operation, continuous operations on the same stream can no longer be performed, and a new stream needs to be recreated for operation.

Also, because forEach()the method is a blocking operation, it can create performance issues when dealing with large amounts of data. If operations need to be performed in parallel for processing efficiency, forEachOrdered()the method or parallelStream()method can be used. forEachOrdered()The method forEach()is similar to the method, but it guarantees that the elements are processed in the original order; parallelStream()the method can convert the stream to a parallel stream, performing operations in parallel on multi-core processors.

forEachOrdered(Consumer<? super T> action)

forEachOrdered()The method is Streama final operation method in the class, which receives a Consumerfunction as a parameter, which is used to perform the specified operation on each element in the stream, forEach()similar to the method. The difference is that forEachOrdered()the methods are guaranteed to execute operations sequentially in the original order of the elements in the stream.

For example, suppose there is a list containing multiple strings, and now each string needs to be converted into lowercase letters and output. The output order must be consistent with the original order, which can be achieved by using the method forEachOrdered():

List<String> strList = Arrays.asList("Java", "Stream", "API");
strList.stream()
       .map(String::toLowerCase)
       .forEachOrdered(System.out::println);

In the above code, first create one from the string list Stream, then execute String::toLowerCasethe method on each string, that is, convert the string to lowercase letters, and finally forEachOrdered()execute the operation on each element through the method System.out::println, that is, output the element to the console. Since the method was called forEachOrdered(), the order of the output remains the same as the original order.

Note that since forEachOrdered()the method is a final action method, it cannot return any value. If you need to convert the elements in the stream to another object such as collection or array, you can use collect()the method. Also, since forEachOrdered()the method is a blocking operation, it may cause performance issues when dealing with large amounts of data. If you need to execute operations in parallel for processing efficiency, you can use parallelStream()the method.

toArray()

The toArray() method is a terminating operation that converts the elements in the Stream object into an array and returns it. This method does not receive any parameters and will return an array of Object type, which can be cast using generic type inference.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the toArray() method.
  3. This method converts the elements in the Stream object into an array of Object type and returns the array.

For example, the following code demonstrates how to use the toArray() method to convert elements in a string stream to an array:

List<String> list = Arrays.asList("apple", "banana", "orange", "pear");
Object[] array = list.stream().toArray();
System.out.println(Arrays.toString(array)); // 输出 [apple, banana, orange, pear]

The above code creates a list of String types and converts it into a Stream object. Next, the toArray() method is called, which converts the elements in the Stream object into an array of Object type and returns the array. Finally, use the Arrays.toString() method to convert the array to a string and output it to the console.

It should be noted that since the toArray() method returns an array of Object type, it is necessary to use generic type inference for forced type conversion. For example, if you want to convert an element of type String to an array of type String, you can use the following code:

String[] strArray = list.stream().toArray(String[]::new);

Here, we use the form of method reference, and pass the constructor String[]::new as a parameter to the toArray() method, so as to convert the array of Object type into an array of String type.

toArray(IntFunction<A[]> generator)

The toArray(IntFunction<A[]> generator) method is a termination operation, which is used to convert the elements in the Stream object into a new array of the specified type and return it. This method receives an IntFunction function as a parameter, which is used to create a new array of the specified size to accommodate all elements in the Stream object.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the toArray(IntFunction<A[]> generator) method and pass in an IntFunction function.
  3. This method will use the IntFunction function to create a new array of the specified size and convert the elements in the Stream object into the array.

For example, the following code demonstrates how to use the toArray() method and a Lambda expression to convert elements in a string stream to an array of type String:

List<String> list = Arrays.asList("apple", "banana", "orange", "pear");
String[] strArray = list.stream().toArray(size -> new String[size]);
System.out.println(Arrays.toString(strArray)); // 输出 [apple, banana, orange, pear]

The above code creates a list of String types and converts it into a Stream object. Next call the toArray() method and pass in a Lambda expression that creates an array of type String based on the given size. This method will use a Lambda expression to create a new array and convert the elements in the Stream object into the array. Finally, use the Arrays.toString() method to convert the array to a string and output it to the console.

It should be noted that since we need to create an array of a specified type, we need to use generics and perform type conversion. In the above example, we used the Lambda expression (size -> new String[size]) to create a new array of String type. According to the value of size, this expression will return an array of type String of the specified size.

reduce(BinaryOperator<T> accumulator)

The reduce(BinaryOperator<T> accumulator) method is a terminating operation that reduces all elements to a single result. This method receives a BinaryOperator function as a parameter, which is used to perform the accumulation operation on the elements in the stream.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the reduce(BinaryOperator<T> accumulator) method and pass in a BinaryOperator function.
  3. This method will perform the specified accumulation operation on the entire stream and return an Optional object containing the result.

For example, the following code demonstrates how to use the reduce() method to calculate the sum of all elements in a list of integers:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list.stream().reduce((a, b) -> a + b);
result.ifPresent(System.out::println); // 输出15

The above code creates a list of type Integer and converts it into a Stream object. Next call the reduce() method, which performs the accumulation operation on each element and returns an Optional object containing the result. Finally, use the ifPresent() method to print the result, because the reduce() method returns an Optional object to prevent null pointer exceptions.

In addition to the above version reduce(BinaryOperator<T> accumulator) without a starting value, there is also a version reduce(T identity, BinaryOperator<T> accumulator) containing a starting value. The first parameter identity in this method represents the initial value. Null pointer exceptions can be avoided, and the result at the beginning is the initial value. For example, the following code demonstrates how to use the reduce() method with a starting value to calculate the sum of all elements in a list of integers:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int result = list.stream().reduce(0, (a, b) -> a + b);
System.out.println(result); // 输出15

 The above code creates a list of type Integer and converts it into a Stream object. Next call the reduce() method, specify an initial value of 0, perform an accumulation operation on each element and return the final result. The result is printed at the end, because the reduce() method returns primitive data types.

 reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)

The reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) method is a terminating operation that reduces all elements into a single result. This method receives three parameters: the first parameter is the initial value identity, the second parameter is the BiFunction function, which is used to convert each element into a certain type U, and perform cumulative operations with the previous partial result, and the third The parameter is the BinaryOperator function, which is used to combine all partial results to obtain the final result.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) method, and pass in an initial value, a BiFunction function and a BinaryOperator function.
  3. This method will perform the specified accumulate operation on the entire stream and return the result.

For example, the following code demonstrates how to use the reduce() method to calculate the sum of the lengths of all elements in a list of strings:

List<String> list = Arrays.asList("java", "python", "ruby");
int result = list.stream().reduce(0, (sum, str) -> sum + str.length(), Integer::sum);
System.out.println(result); // 输出14

The above code creates a list of String types and converts it into a Stream object. Next call the reduce() method, specify an initial value of 0, add the length of each element to the initial value, and use the Integer::sum method to combine all partial results. Finally, print the result, because the reduce() method returns the basic data type, there is no need to use the isPresent() method to determine whether the result exists.

It should be noted that since this method can be operated in parallel, each partial result needs to be accumulated using the BiFunction function, and the final result needs to be combined using the BinaryOperator function. If there are multiple partial results in the stream, the BinaryOperator function is called to combine them into one result.

 collect(Collector<? super T,A,R> collector)

collect(Collector<? super T,A,R> collector)method is a method provided by the interface in Java 8 Streamto collect the elements in the stream into a container object. This method receives a Collectorobject as a parameter, which defines how to collect the elements in the stream and put the result into a container object.

Here is an example of usage:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamCollectExample {
    public static void main(String[] args) {
        List<String> names = Stream.of("Tom", "Jerry", "Mickey", "Minnie")
                .filter(name -> name.startsWith("M"))
                .collect(Collectors.toList());
        System.out.println(names); // [Mickey, Minnie]

        List<Integer> numbers = Stream.iterate(1, n -> n + 1)
                .limit(10)
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println(numbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

        int sum = Stream.of(1, 2, 3, 4, 5)
                .collect(Collectors.summingInt(Integer::intValue));
        System.out.println(sum); // 15

        String joined = Stream.of("Hello", "world")
                .collect(Collectors.joining(", "));
        System.out.println(joined); // "Hello, world"
    }
}

The code above shows four collect()examples of using the . In the first example, use Collectors.toList()to collect strings in the stream that start with the letter "M" into a Listobject. In the second example, Collectors.toCollection(ArrayList::new)collect the first 10 integers in the stream into a ArrayListobject using . In the third example, use Collectors.summingInt(Integer::intValue)calculates the sum of the integers in the stream. In the fourth example, use Collectors.joining(", ")to concatenate the strings in the stream into one string.

When using collect()the method, you need to pay attention to Collectorthe definition of the object, which defines the way to collect stream elements. Commonly used Collectorimplementation classes are toList(), toSet(), toMap(), summingInt(), joining()etc., which can be selected according to specific needs.

collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)

collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)method is a method provided by the interface in Java 8 Streamto collect the elements in the stream into a container object. This method receives three parameters:

  • supplier: Provides a factory method for container objects.
  • accumulator: An accumulator function that collects elements in a stream.
  • combiner: A function that merges two container objects into one.

Here is an example of usage:

import java.util.ArrayList;
import java.util.List;

public class StreamCollectExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Tom");
        list.add("Jerry");
        list.add("Mickey");
        list.add("Minnie");

        List<String> result = list.stream().collect(
                ArrayList::new,
                (l, s) -> {
                    if (s.startsWith("M")) {
                        l.add(s);
                    }
                },
                List::addAll);

        System.out.println(result); // [Mickey, Minnie]
    }
}

The above code shows collect()an example of custom collection using the method. First, a object is created ArrayListas a container object, and some strings are added to the object. Then stream()get the stream through the method, and collect()do a custom collection through the method.

During this collection, use ArrayList::newto provide a ArrayListfactory method to create container objects; use to (l, s) -> {...}define an accumulator function in which only strings starting with the letter "M" are added to the container object; use to define List::addAlla merge container object Function that combines the elements of multiple container objects into one. Ultimately, you get a list containing strings starting with the letter "M".

It should be noted that when using collect()the method, different collection methods need to be selected according to specific needs, Supplier<R>and BiConsumer<R, ? super T>the correct implementation BiConsumer<R, R>of the three function interfaces of and can successfully collect elements in the stream.

max(Comparator<? super T> comparator)

The max(Comparator<? super T> comparator) method is a terminating operation that returns the largest element in this stream, comparing elements according to the specified Comparator. The returned type is Optional<T>, or an empty Optional object if the stream is empty.

This method can only be used on streams of finite length, because comparison operations need to be performed on the entire stream to find the largest element. The time complexity of this method execution is O(n), where n is the number of elements in the stream.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the max(Comparator<? super T> comparator) method and pass in a Comparator object.
  3. This method will perform a comparison operation on the entire stream and find the largest element.
  4. The return type is Optional<T>, and the value in it can be obtained through the .get() method.

For example, the following code demonstrates how to use the max() method to find the largest element in a stream:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = list.stream().max(Integer::compare);
if(max.isPresent()) {
    System.out.println("The maximum element is " + max.get());
}

The output is: "The maximum element is 5", because 5 is the largest element in the list. Note that the max() method returns an Optional object, so it is necessary to determine whether there is a maximum value before performing other operations.

min(Comparator<? super T> comparator)

The min(Comparator<? super T> comparator) method is a terminating operation that returns the smallest element in this stream, comparing elements according to the specified Comparator. The returned type is Optional<T>, or an empty Optional object if the stream is empty.

This method can only be used on streams of finite length, because comparison operations need to be performed on the entire stream to find the smallest element. The time complexity of this method execution is O(n), where n is the number of elements in the stream.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the min(Comparator<? super T> comparator) method and pass in a Comparator object.
  3. This method will perform a comparison operation on the entire stream and find the smallest element.
  4. The return type is Optional<T>, and the value in it can be obtained through the .get() method.

For example, the following code demonstrates how to use the min() method to find the smallest element in a stream:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> min = list.stream().min(Integer::compare);
if(min.isPresent()) {
    System.out.println("The minimum element is " + min.get());
}

The output is: "The minimum element is 1", because 1 is the minimum element in the list. Note that the min() method returns an Optional object, so it is necessary to determine whether there is a minimum value before performing other operations.

 count()

count()method is the method used to count the number of elements in the stream.

Here is an example of usage:

import java.util.Arrays;
import java.util.List;

public class StreamCountExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        
        long count = list.stream().count();
        System.out.println("Count: " + count); // 输出 Count: 5
    }
}

The above code shows how to use count()the method to count the number of elements in the stream. First a list of integers is created listand then stream()converted to a stream by the method. Then, use count()the method to get the number of elements in the stream, get a long integer value count, and finally print it out.

It should be noted that count()the method returns a long value representing the number of elements in the stream. If the stream is empty, the return value is 0. Also, since count()the method returns a terminating operation, no other operations can be performed on the same stream after calling this method.

 

 allMatch(Predicate<? super T> predicate)

allMatch(Predicate<? super T> predicate)The method is used to judge whether all elements in the stream meet the specified conditions, and return if they all meet true, otherwise return false. PredicateThe parameter is a judgment condition, which accepts a parameter of type T and returns a result of type boolean.

Here is allMatch()an example usage of the method:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

// 判断是否所有元素都大于 0
boolean allPositive = list.stream()
        .allMatch(x -> x > 0);

System.out.println(allPositive); // true

// 判断是否所有元素都小于 3
boolean allLessThanThree = list.stream()
        .allMatch(x -> x < 3);

System.out.println(allLessThanThree); // false

In the above code, an integer list containing 1 to 5 is first created, and then allMatch()the method is used to judge whether the elements in the list are all greater than 0 or less than 3, and output the result to the console.

allMatch()Note that the method returns when the stream is empty true.

anyMatch(Predicate<? super T> predicate)

anyMatch(Predicate<? super T> predicate)The method is used to judge whether there is at least one element in the stream that meets the specified condition, and return if it exists true, otherwise return false. PredicateThe parameter is a judgment condition, which accepts a parameter of type T and returns a result of type boolean.

Here is anyMatch()an example usage of the method:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

// 判断是否存在大于 3 的元素
boolean existsGreaterThanThree = list.stream()
        .anyMatch(x -> x > 3);

System.out.println(existsGreaterThanThree); // true

// 判断是否存在小于 0 的元素
boolean existsLessThanZero = list.stream()
        .anyMatch(x -> x < 0);

System.out.println(existsLessThanZero); // false

In the above code, an integer list containing 1 to 5 is first created, and then anyMatch()the method is used to judge whether there are elements greater than 3 and elements less than 0 in the list, and output the results to the console.

anyMatch()Note that the method returns when the stream is empty false.

 noneMatch(Predicate<? super T> predicate)

The noneMatch(Predicate<? super T> predicate) method is a terminating operation that checks whether all elements in the stream do not satisfy the specified Predicate condition. Returns true if none of the elements satisfy the condition; otherwise returns false.

The time complexity of this method execution is O(n), where n is the number of elements in the stream.

The specific usage is as follows:

  1. Create a Stream object containing multiple elements.
  2. Call the noneMatch(Predicate<? super T> predicate) method and pass in a Predicate object.
  3. This method will perform a check operation on the entire stream and return a boolean indicating whether all elements fail the condition.

For example, the following code demonstrates how to use the noneMatch() method to check whether all elements in a stream are even:

List<Integer> list = Arrays.asList(1, 3, 5, 7);
boolean result = list.stream().noneMatch(x -> x % 2 == 0);
if(result) {
    System.out.println("All the elements are odd numbers.");
} else {
    System.out.println("There are even numbers in the list.");
}

The output is: "All the elements are odd numbers." because there are no even numbers in the given list. If there are even numbers in the list, the output will be "There are even numbers in the list.".

findAny()

findAny()method is used to return any element in the current stream. It can be filter()used with the method to return as soon as an element matching the criteria is found.

Here is an example of usage:

import java.util.Arrays;
import java.util.List;

public class StreamFindAnyExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        
        Integer result = list.stream()
                             .filter(n -> n % 2 == 0)
                             .findAny()
                             .orElse(null);

        System.out.println(result); // 输出 2 或 4
    }
}

The above code shows how to use findAny()the method to return any element in the current stream. First a list of integers is created listand then stream()converted to a stream by the method. Next, use filter(n -> n % 2 == 0)the method to get a new stream containing only even elements, and use findAny()the method to return any one of the elements. The return value may be 2 or 4 because there are multiple even elements in the stream. Finally, orElse(null)the return value is processed by the method and printed out.

Note that if there are no elements in the stream, findAny()the method will return an empty Optionalobject. Therefore, in the above code, orElse(null)the possibly null return value is handled by the method.

findFirst()

findFirst()method is used to return the first element in the current stream. It can be filter()used with the method to return as soon as an element matching the criteria is found.

Here is an example of usage:

import java.util.Arrays;
import java.util.List;

public class StreamFindFirstExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        
        Integer result = list.stream()
                             .filter(n -> n % 2 == 0)
                             .findFirst()
                             .orElse(null);

        System.out.println(result); // 输出 2
    }
}

The above code shows how to use findFirst()the method to return the first element in the current stream. First a list of integers is created listand then stream()converted to a stream by the method. Next, use filter(n -> n % 2 == 0)the method to get a new stream containing only even elements, and use findFirst()the method to return the first element in it. Since there are multiple even elements in the stream, the return value is 2. Finally, orElse(null)the return value is processed by the method and printed out.

Note that if there are no elements in the stream, findFirst()the method will return an empty Optionalobject. Therefore, in the above code, orElse(null)the possibly null return value is handled by the method. Also, if the elements in the stream are unordered, any one of them will be returned.

 

Guess you like

Origin blog.csdn.net/Ascend1977/article/details/131095060