An overview,

Stream is the key abstraction for dealing with collections in Java8. It can specify what you want to do with collections, and can perform very complex operations like finding, filtering, and mapping data. Manipulating collection data using the Stream API is similar to database queries executed using SQL. You can also use the Stream API to perform operations in parallel. In short, the Stream API provides an efficient and easy-to-use way to process data.

Features:

1. It is not a data structure and does not save data.

2. It does not modify the original data source, but saves the data after operation to another object. (Reservation: After all, the PEEK method can modify elements in the stream.)

3. Lazy evaluation. During the intermediate process, the flow only records the operation and does not execute it immediately.

Second, usage,

category methods describe
traverse void forEach(Consumer<? super T> action) Traversal operation, traversal performs the corresponding action for Consumer
Screening/slicing Stream filter(Predicate<? super T> predicate

Stream distinct()

Stream limit(long maxSize)

Stream skip(long n)
The filtering operation, based on the Predicate, determines that the result will remain true and the result will still be a stream

Rerun operation, filter out the results that do not repeat, return the result is still a stream

Truncation limit operation, only take the first maxSize data, return the result is still a stream

Skip operation, skip n data, fetch the following data, return the result is still a stream
The sorting Stream sorted(Comparator<? super T> comparator) Sort the elements in the flow, and the result is still a flow
mapping Stream map(Function<? super T, ? extends R> mapper)

Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
The conversion operation, according to the argument T, is converted to type R, and the result is still a stream

The conversion operation, according to parameter T, converts to a stream of type R. Multiple streams of type R are generated and the result is still a stream
matching boolean anyMatch(Predicate<? super T> predicate)

boolean allMatch(Predicate<? super T> predicate)

boolean noneMatch(Predicate<? super T> predicate)
Determines whether there is a match. Based on the Predicate, determines whether a match is successful

Determines whether all matches are successful based on the Predicate

Determine whether none of them match, and then determine whether all of them don’t match based on the Predicate
To find the Optional findAny()

Optional findFirst()
Find operation that queries any element in the current stream and returns Optional

Find operation that queries the first element in the current flow and returns Optional
reduction T reduce(T identity, BinaryOperator accumulator)

Optional max(Comparator<? super T> comparator)

Optional min(Comparator<? super T> comparator)
A reduction operation that returns a result of the same type after operating on data of the same type. Such as adding and multiplying two integers.

Obtain the maximum value according to the comparison result calculated by the Comparator

Find the minimum value according to the comparison result calculated by the Comparator
Summary statistics <R, A> R collect(Collector<? super T, A, R> collector)

long count()
Summary operations and corresponding processing results.

Statistics the amount of data in the flow
The final operation R collect(Collector<? super T, A, R> collector) Usually occurs at the end of a pipe transfer operation to mark the end of a stream

Three, usage,

1. Common creation methods for streams

1.1 Use the Stream() and parallelStream() methods under Collection

List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); ParallelStream <String> parallelStream = list.parallelstream (); // Get a parallel streamCopy the code

1.2 Convert Arrays to streams using the stream() method of Arrays

Integer[] nums = new Integer[10];
Stream<Integer> stream = Arrays.stream(nums);
Copy the code

1.3 Use static methods in Stream: of(), iterate(), generate()

Stream < Integer > Stream = Stream of (6); Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6); stream2.forEach(System.out::println); // 0 2 4 6 8 10 Stream<Double> stream3 = Stream.generate(Math::random).limit(2); stream3.forEach(System.out::println);Copy the code

1.4 Convert each line to a stream using the bufferedreader.lines () method

BufferedReader reader = new BufferedReader(new FileReader("F:\\test_stream.txt"));
Stream<String> lineStream = reader.lines();
lineStream.forEach(System.out::println);
Copy the code

1.5 Use the pattern.splitasstream () method to separate strings into streams

Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);
Copy the code

2. Intermediate operations for streams

Skip (n) : Skip N elements, with limit(n) to achieve paging distinct: Remove duplicate elements by hashCode() and equals() of elements in the stream

Stream<Integer> stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
 
Stream<Integer> newStream = stream.filter(s -> s > 5) //6 6 7 9 8 10 12 14 14
        .distinct() //6 7 9 8 10 12 14
        .skip(2) //9 8 10 12 14
        .limit(2); //9 8
newStream.forEach(System.out::println);
Copy the code

2.2 Mapping Map: Takes as an argument a function that is applied to each element and maps it to a new element. FlatMap: Takes a function as an argument, replaces each value in the stream with another stream, and joins all streams into one stream.

A List < String > List = Arrays. AsList (" a, b, c ", "1, 2, 3"); Stream<String> s1 = list.stream().map(s -> s.replaceall (",", "")); s1.forEach(System.out::println); // ABC 123 Stream<String> s3 = list.stream().flatmap (s -> {// convert each element to a Stream String[] split = s.split(","); Stream<String> s2 = Arrays.stream(split); return s2; }); s3.forEach(System.out::println); // a b c 1 2 3Copy the code

Sorted () : sorted by default. All data in a stream needs to be sorted using the Comparable interface. (Comparator com

List<String> list = Arrays.asList("aa", "ff", "dd"); Sorted ().foreach (system.out ::println); // aa dd ff Student s1 = new Student("aa", 10); Student s2 = new Student("bb", 20); Student s3 = new Student("aa", 30); Student s4 = new Student("dd", 40); List<Student> studentList = Arrays.asList(s1, s2, s3, s4); // Custom sort: First in ascending order by name, Studentlist.stream (). Sorted (o1, o2) -> { if (o1.getName().equals(o2.getName())) { return o1.getAge() - o2.getAge(); } else { return o1.getName().compareTo(o2.getName()); } } ).forEach(System.out::println);Copy the code

2.4 Consume Peek: Like a map, you can get every element in the stream. But the map receives a Function expression that returns a value; Peek receives the Consumer expression and returns no value.

Student s1 = new Student("aa", 10); Student s2 = new Student("bb", 20); List<Student> studentList = Arrays.asList(s1, s2); studentList.stream() .peek(o -> o.setAge(100)) .forEach(System.out::println); Student{name='bb', age=100}Copy the code

3. Terminate the flow

AllMatch: Receives a Predicate function that returns true only if each element in the stream matches the Predicate, or false if it does not: Predicate receives a Predicate function, which returns true only if every element in the stream does not satisfy the Predicate, false anyMatch otherwise: Receives a Predicate function, which returns true only if one element in the stream satisfies the Predicate, and false findFirst otherwise: FindAny: any element in the stream count: total number of elements in the stream Max: maximum number of elements in the stream min: minimum number of elements in the stream

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); boolean allMatch = list.stream().allMatch(e -> e > 10); //false boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true Integer findFirst = list.stream().findFirst().get(); //1 Integer findAny = list.stream().findAny().get(); //1 long count = list.stream().count(); //5 Integer max = list.stream().max(Integer::compareTo).get(); //5 Integer min = list.stream().min(Integer::compareTo).get(); / / 1Copy the code

3.2 Optional Reduce (BinaryOperator Accumulator) : When executed for the first time, the first parameter of the Accumulator function is the first element in the flow and the second parameter is the second element of the element in the flow. On the second execution, the first argument is the result of the first function execution and the second argument is the third element in the stream. And so on. T reduce(T Identity, BinaryOperator Accumulator) : The flow is the same as above except that when executed for the first time, the first parameter of the Accumulator function is identity and the second parameter is the first element in the flow. U reduce(U identity,BiFunction

accumulator, BinaryOperator combiner) : in serial stream (stream), the method is the same as the second method, namely the third parameter combiner doesn’t work. In parallelStream, we know that the stream is forked and joined by multiple threads. In this case, the execution flow of each thread is the same as that of the second reduce(Identity, Accumulator) method. The third parameter combiner function, The execution result of each thread is treated as a new flow, and the first method reduce(Accumulator) process is used for specification.
,>

// When the number of elements is less than 24, the number of parallel threads is equal to the number of elements. When the number of elements is greater than or equal to 24, the number of threads is equal to the number of elements. List<Integer> List = Arrays. AsList (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24); Integer v = list.stream().reduce((x1, x2) -> x1 + x2).get(); System.out.println(v); // 300 Integer v1 = list.stream().reduce(10, (x1, x2) -> x1 + x2); System.out.println(v1); //310 Integer v2 = list.stream().reduce(0, (x1, x2) -> { System.out.println("stream accumulator: x1:" + x1 + " x2:" + x2); return x1 - x2; }, (x1, x2) -> { System.out.println("stream combiner: x1:" + x1 + " x2:" + x2); return x1 * x2; }); System.out.println(v2); // -300 Integer v3 = list.parallelStream().reduce(0, (x1, x2) -> { System.out.println("parallelStream accumulator: x1:" + x1 + " x2:" + x2); return x1 - x2; }, (x1, x2) -> { System.out.println("parallelStream combiner: x1:" + x1 + " x2:" + x2); return x1 * x2; }); System.out.println(v3); / / 197474048Copy the code

3.3 Collection Operations

3.3.1 Collector Tool library: Collectors

Student s1 = new Student("aa", 10,1); Student s2 = new Student("bb", 20,2); Student s3 = new Student("cc", 10,3); List<Student> list = Arrays.asList(s1, s2, s3); // Install a list list <Integer> ageList = list.stream().map(Student::getAge).collect(Collectors. ToList ()); Set<Integer> ageSet = list.stream().map(Student::getAge).collect(Collectors. ToSet ()); // [20, 10] // convert to map. Otherwise, an error is reported: Map<String, Integer> studentMap = list.stream().collect(Collectors. ToMap (Student::getName, Student::getAge)); // {cc=10, bb=20, Aa =10} // String separator Connection String joinName = list.stream().map(Student::getName).collect(Collectors. Joining (",", "(", ")"); Long count = list.stream().collect(Collectors. Counting ()); // (aa,bb,cc) // Aggregation //1. // 3 //2. Maximum age (same as minimum minBy) Integer maxAge = list.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get(); Age Integer sumAge = list.stream().collect(Collectors. SummingInt (Student::getAge)); // 20 //3. 40 / / / / 4. The average age of Double averageAge = list. The stream () collect (Collectors. AveragingDouble Student: : getAge ()); // take all of the above methods DoubleSummaryStatistics statistics = list.stream().collect(Collectors.summarizingDouble(Student::getAge)); System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage()); // Grouping Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors. GroupingBy (Student::getAge)); // Grouping Map<Integer, List<Student>> ageMap = list.stream(). Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getType, Collectors.groupingBy(Student::getAge))); // Divide into two parts, one is over 10 years old, Part of less than or equal to 10 Map < Boolean, List < Student > > partMap = List. The stream () collect (Collectors. PartitioningBy (v - > v.g etAge () > 10));  // Integer allAge = list.stream().map(Student::getAge).collect(class.reduce (Integer::sum)).get(); / / 40Copy the code

3.3.2 rainfall distribution on 10-12 Collectors. ToList ()

Public static <T> Collector<T,? , List<T>> toList() { return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, CH_ID); } public <T> Collector<T,? , List<T>> toList() { Supplier<List<T>> supplier = () -> new ArrayList(); BiConsumer<List<T>, T> accumulator = (list, t) -> list.add(t); BinaryOperator<List<T>> combiner = (list1, list2) -> { list1.addAll(list2); return list1; }; Function<List<T>, List<T>> finisher = (list) -> list; Set<Collector.Characteristics> characteristics = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); return new Collector<T, List<T>, List<T>>() { @Override public Supplier supplier() { return supplier; } @Override public BiConsumer accumulator() { return accumulator; } @Override public BinaryOperator combiner() { return combiner; } @Override public Function finisher() { return finisher; } @Override public Set<Characteristics> characteristics() { return characteristics; }}; }Copy the code