Point wave attention is not lost, a key three even good luck!

First paste a few cases, students with excellent skills can challenge:

  1. Select employees with salary greater than 8000 from the employee set and place them in the new set.
  2. Collect the highest salary, average salary and sum of salary of employees.
  3. Rank employees in order of salary from highest to lowest, with the youngest of the same earners coming first.
  4. Divide employees by gender, divide employees by gender and region, and divide employees into two parts according to whether they are paid more than 8000.

It’s not too hard to do with traditional iteration, but the code is redundant and can be compared to a Stream.

A description of the Stream

Java 8 has been a very successful release, and the addition of Stream, along with Lambda, has made it very easy to manipulate collections.

So what is a Stream?

The set of elements that Stream will process is considered a Stream, and the Stream API is used to perform operations on the elements in the Stream, such as filtering, sorting, aggregating, and so on.

Streams can be created from arrays or collections. There are two types of operations for streams:

  1. Intermediate operations, which return a new stream at a time, can be multiple.
  2. Terminal operation: Each stream can perform only one terminal operation. After the terminal operation, the stream cannot be used again. A terminal operation produces a new set or value.

In addition, Stream has several features:

  1. A stream does not store data, but evaluates it according to specific rules, generally producing output.
  2. Stream does not change the data source, and typically produces a new collection or a value.
  3. Stream has a delayed execution property, where intermediate operations are executed only when terminal operations are called.

2 Stream creation

Streams can be created from collections arrays.

1, through the Java. Util. Collection. Set stream () method is used to create flow

List<String> list = Arrays.asList("a", "b", "c"); // Create a sequential Stream<String> Stream = list.stream(); // create a parallelStream Stream<String> parallelStream = list.parallelstream ();Copy the code

Java.util.array.stream (T[] array

Int [] array =,3,5,6,8 {1}; IntStream stream = Arrays.stream(array);Copy the code

Iterate (), iterate(), generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println); // 0 2 4 6 8 10

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);
Copy the code

Output result:

0 3 69 0.6796156909271994 0.1914314208854283 0.8116932592396652

ParallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream parallelStream For example, odd numbers in the filter set are filtered. The processing differences between the two are as follows:

If the amount of data in the stream is large enough, parallel streams can speed things up.

Instead of creating parallel streams directly, parallel() can replace sequential streams with parallel streams:

Optional<Integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();
Copy the code

3. Use of Stream

Before using Stream, understand the concept of Optional.

The Optional class is a container object that can be null. The isPresent() method returns true if the value exists, and calling the get() method returns the object. See the Rookie Tutorial Java 8 Optional class for more details

Next, you’ll be bombarded with code! I’ll use 20 examples to illustrate the use of Stream, and you’ll get a good grasp of it once you type through the code.

The employee class used in the case

This is the employee class used in the later example:

List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, "male", "New York")); personList.add(new Person("Jack", 7000, "male", "Washington")); personList.add(new Person("Lily", 7800, "female", "Washington")); personList.add(new Person("Anni", 8200, "female", "New York")); personList.add(new Person("Owen", 9500, "male", "New York")); personList.add(new Person("Alisa", 7900, "female", "New York")); class Person { private String name; // private int salary; // salary private int age; // Age private String sex; // Gender private String area; Public Person(String name, int salary, int age,String sex,String area) {this.name = name; this.salary = salary; this.age = age; this.sex = sex; this.area = area; } // get and set are omitted.Copy the code

3.1 Traversal/Match (foreach/find/match)

A Stream also supports traversal and matching elements of a similar collection, except that the elements in the Stream are of type Optional. Stream traversal and matching is very simple.

// import has been omitted, please add it yourself, Public class StreamTest {public static void main(String[] args) {List<Integer> List = array.asList (7, 6, 9, 3, 8, 2, 1); List.stream ().filter(x -> x > 6).foreach (system.out ::println); // Match first Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findfirst (); // Match any (for parallel streams) Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findany (); Boolean anyMatch = list.stream().anymatch (x -> x < 6); System.out.println(" match first value: "+ findfirst.get ()); System.out.println(" match any value: "+ findany.get ()); System.out.println(" is there a value greater than 6: "+ anyMatch); }}Copy the code

3.2 Filter

Filtering is an operation that verifies the elements in the stream according to certain rules and extracts the elements that meet the conditions into the new stream.

Case 1: ScreeningIntegerAny element in the collection greater than 7, and print it out

public class StreamTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9); Stream<Integer> stream = list.stream(); stream.filter(x -> x > 7).forEach(System.out::println); }}Copy the code

Expected Results:

8 and 9

Case 2: Select employees whose salary is above 8000 and form a new set. The new collection relies on collect, which will be described in detail later.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); personList.add(new Person("Anni", 8200, 24, "female", "New York")); personList.add(new Person("Owen", 9500, 25, "male", "New York")); personList.add(new Person("Alisa", 7900, 26, "female", "New York")); List<String> fiterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName) .collect(Collectors.toList()); System.out.print(" name above 8000: "+ fiterList); }}Copy the code

Running results:

Name of employee above 8000: [Tom, Anni, Owen]

3.3 Aggregation (Max /min/count)

Max, min, count you are familiar with these words, yes, in mysql we often use them for data statistics. These concepts and usages are also introduced in Java Stream, which greatly facilitates the statistical work of collections and arrays.

Case 1: AcquisitionStringThe longest element in the set.

public class StreamTest { public static void main(String[] args) { List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd"); Optional<String> max = list.stream().max(Comparator.comparing(String::length)); System.out.println(" longest string: "+ max.get()); }}Copy the code

Output result:

Longest string: weoujgsd

Case 2: AcquisitionIntegerThe maximum value in the set.

public class StreamTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6); // Natural sort Optional<Integer> Max = list.stream().max(Integer::compareTo); // Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {@override public int compare(Integer o1,  Integer o2) { return o1.compareTo(o2); }}); System.out.println(" natural sort Max: "+ max.get()); System.out.println(" Custom sort Max: "+ max2.get()); }}Copy the code

Output result:

Maximum value for natural sort: 11 Maximum value for custom sort: 11

Case 3: Get the highest paid employee.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); personList.add(new Person("Anni", 8200, 24, "female", "New York")); personList.add(new Person("Owen", 9500, 25, "male", "New York")); personList.add(new Person("Alisa", 7900, 26, "female", "New York")); Optional<Person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary)); System.out.println(" max.get().getsalary () "); }}Copy the code

Output result:

Maximum employee salary: 9,500

Case 4: CalculationIntegerThe number of elements in the set greater than 6.

import java.util.Arrays; import java.util.List; public class StreamTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9); long count = list.stream().filter(x -> x > 6).count(); System.out.println(" number of elements in list greater than 6: "+ count); }}Copy the code

Output result:

Number of elements in list greater than 6:4

3.4 mapping (map/flatMap)

Mapping, you can map elements of one flow to another flow according to certain mapping rules. Divided into map and flatMap:

  • map: Takes a function as an argument that is applied to each element and mapped 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 a single stream.

Case 1: Uppercase all elements of an English string array. Integer array +3 for each element.

public class StreamTest { public static void main(String[] args) { String[] strArr = { "abcd", "bcdd", "defde", "fTr" };  List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList()); List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11); List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList()); System.out.println(" each element uppercase: "+ strList); System.out.println(" each element +3: "+ intListNew); }}Copy the code

Output result:

Each element caps: [ABCD, BCDD, DEFDE, FTR] Each element +3: [4, 6, 8, 10, 12, 14]

Case 2: Increase the salary of all employees by 1000.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); personList.add(new Person("Anni", 8200, 24, "female", "New York")); personList.add(new Person("Owen", 9500, 25, "male", "New York")); personList.add(new Person("Alisa", 7900, 26, "female", "New York")); List<Person> personListNew = personlist.stream ().map(Person -> {Person personNew = new Person(person.getName(), 0, 0, null, null); personNew.setSalary(person.getSalary() + 10000); return personNew; }).collect(Collectors.toList()); Println (" + personList.get(0).getName() + "-->" + PersonList.get (0).getsalary ()); Println (" + PersonListNew.get (0).getName() + "-->" + PersonListNew.get (0).getsalary ()); List<Person> personListNew2 = personlist.stream ().map(Person -> {person.setSalary(person.getsalary () +) 10000); return person; }).collect(Collectors.toList()); Println (" + PersonList.get (0).getName() + "-->" + PersonListNew.get (0).getsalary ()); Println (" + PersonListNew2.get (0).getName() + "-->" + PersonListNew.get (0).getsalary ()); }}Copy the code

Output result:

Before one change: Tom – >8900 After one change: Tom – >18900 Before two changes: Tom – >18900 After two changes: Tom – >18900

Case 3: Combine two character arrays into a new character array.

public class StreamTest { public static void main(String[] args) { List<String> list = Arrays.asList("m,k,l,a", "1 hc-positie"); List<String> listNew = list.stream().flatmap (s -> {// Convert each element to a stream String[] split = s.split(","); Stream<String> s2 = Arrays.stream(split); return s2; }).collect(Collectors.toList()); System.out.println(" set before processing: "+ list); System.out.println(" processed collection: "+ listNew); }}Copy the code

Output result:

Before processing collection: [m – k – l – a, 1-3-5] after processing collection: [m, k, l, a, 1, 3, 5]

3.5 reduction (reduce)

Reduction, also known as reduction, as the name implies, is to reduce a stream to a value, can achieve the sum of sets, products and maximization operations.

Case 1: BegIntegerThe sum, product, and maximum value of the elements of a set.

public class StreamTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4); 1 Optional<Integer> sum = list.stream().reduce((x, y) -> x + y); 2 Optional<Integer> sum2 = list.stream().reduce(Integer::sum); 3 Integer sum3 = list.stream().reduce(0, Integer::sum); // Find the product Optional<Integer> product = list.stream().reduce((x, y) -> x * y); 1 Optional<Integer> Max = list.stream().reduce((x, y) -> x > y? x : y); 2 Integer max2 = list.stream().reduce(1, Integer:: Max); System. The out. Println (" summation: list "+ sum. The get () +", "+ sum2. The get () +", "+ sum3); System.out.println(" product: "+ product.get()); System.out.println("list summation: "+ max.get() + "," + max2); }}Copy the code

Output result:

List summation: 29,29,29 list quadrature: 2112 list summation: 11,11

Case 2: Find the sum of all employees’ salaries and the highest salary.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); personList.add(new Person("Anni", 8200, 24, "female", "New York")); personList.add(new Person("Owen", 9500, 25, "male", "New York")); personList.add(new Person("Alisa", 7900, 26, "female", "New York")); 1: Optional<Integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum); // Get the sum of the salary.  Integer sumSalary2 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), (sum1, sum2) -> sum1 + sum2); SumSalary3 = personlist.stream ().reduce(0, (sum, p) -> sum += p.getsalary (), Integer::sum); Integer maxSalary = personlist.stream ().reduce(0, (Max, p) -> Max > p.getsalary ()? max : p.getSalary(), Integer::max); Integer maxSalary2 = personlist.stream ().reduce(0, (Max, p) -> Max > p.getsalary ()? max : p.getSalary(), (max1, max2) -> max1 > max2 ? max1 : max2); Println (" + salary2 + "," + sumSalary2 + "," + sumSalary3); Println (" maxSalary: "+ maxSalary2 "," + maxSalary2); }}Copy the code

Output result:

Total salary: 49300,49300,49300 maximum salary: 9500,9500

3.6 collect (collect)

It is arguably the most varied and feature-rich part of the collection. Literally, a stream is collected, either as a value or as a new collection.

Collect mainly depends on the Java. Util. Stream. Collectors class built-in static methods.

3.6.1 track the collection (toList/toSet/toMap)

Since the stream does not store data, after the data in the stream is processed, the data in the stream needs to be regrouped into a new collection. ToList, toSet, and toMap are commonly used, as well as toCollection, toConcurrentMap, and other more complex usages.

Here’s an example of toList, toSet, and toMap:

public class StreamTest {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
		List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
		Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());

		List<Person> personList = new ArrayList<Person>();
		personList.add(new Person("Tom", 8900, 23, "male", "New York"));
		personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
		personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
		personList.add(new Person("Anni", 8200, 24, "female", "New York"));
		
		Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
				.collect(Collectors.toMap(Person::getName, p -> p));
		System.out.println("toList:" + listNew);
		System.out.println("toSet:" + set);
		System.out.println("toMap:" + map);
	}
}
Copy the code

Running results:

ToList: [6, 4, 6, 6, 20] toSet: [4, 20, 6] toMap: {Tom=mutest.Person@5fd0d5ae, Anni=mutest.Person@2d98a335}

3.6.2 statistics (count/averaging)

Collectors provides a series of static methods for collecting statistics:

  • Count:count
  • Average:averagingInt,averagingLong,averagingDouble
  • The most value:maxBy,minBy
  • Sum:summingInt,summingLong,summingDouble
  • Count all of the above:summarizingInt,summarizingLong,summarizingDouble

Case: count the number of employees, average salary, total salary and maximum salary.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); Long count = personlist.stream ().collect(Collectors. Counting ()); Average wages / / o Double business = personList. Stream () collect (Collectors. AveragingDouble (Person: : getSalary)); // Collectors Optional<Integer> Max = personlist.stream ().map(Person::getSalary).collect(Collectors. MaxBy (Integer::compare));  Integer sum = personlist.stream ().collect(Collectors. SummingInt (Person::getSalary)); // Collect all information at a time DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary)); System.out.println(" number of employees: "+ count); System.out.println(" employee average: "+ average); System.out.println(" sum: "+ sum); System.out.println(" collect "); }}Copy the code

Running results:

Total number of employees: 3 Average salary of employees: 7900.0 Total salary of employees: 23,700 DoubleSummaryStatistics {count = 3, the sum = 23700.000000, min = 7000.000000, business = 7900.000000, Max = 8900.000000}

3.6.3 group (partitioningBy/groupingBy)

  • Partition:streamAccording to the conditions are divided into twoMapFor example, employees are divided into two parts according to whether their salary is higher than 8000.
  • Grouping: Divide the collection into multiple maps, such as employees grouped by gender. There are single-level and multi-level grouping.

Case: Divide employees into two parts according to whether their salary is higher than 8000; Group employees by gender and region

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, "male", "New York")); personList.add(new Person("Jack", 7000, "male", "Washington")); personList.add(new Person("Lily", 7800, "female", "Washington")); personList.add(new Person("Anni", 8200, "female", "New York")); personList.add(new Person("Owen", 9500, "male", "New York")); personList.add(new Person("Alisa", 7900, "female", "New York")); // Group employees by salary above 8000 Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000)); Map<String, List<Person>> group = personlist.stream ().collect(Collectors. GroupingBy (Person::getSex)); // Group employees by gender first, Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea))); System.out.println(" employees grouped by salary > 8000: "+ part); System.out.println(" employee grouped by gender: "+ group); System.out.println(" employee by gender, region: "+ group2); }}Copy the code

Output result:

Employees grouped according to whether their salary is greater than 8000: {false=[mutest.Person@2d98a335, mutest.Person@16b98e56, mutest.Person@7ef20235], true=[mutest.Person@27d6c5e0, mutest.Person@4f3f5b24, mutest.Person@15aeb7ab]} Employees grouped by gender: {female=[mutest.Person@16b98e56, mutest.Person@4f3f5b24, mutest.Person@7ef20235], male=[mutest.Person@27d6c5e0, mutest.Person@2d98a335, mutest.Person@15aeb7ab]} Employees by gender and region: {female={New York=[mutest.Person@4f3f5b24, mutest.Person@7ef20235], Washington=[mutest.Person@16b98e56]}, male={New York=[mutest.Person@27d6c5e0, mutest.Person@15aeb7ab], Washington=[mutest.Person@2d98a335]}}Copy the code

3.6.4 radar echoes captured joint (joining)

Joining joins elements in a stream into a string using a specific concatenation (or, if not, directly).

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(",")); System.out.println(" Names of all employees: "+ names); List<String> list = Arrays.asList("A", "B", "C"); String string = list.stream().collect(Collectors.joining("-")); System.out.println(" concatenated string: "+ string); }}Copy the code

Running results:

Name of all employees: Tom,Jack,Lily

3.6.5 reduction (reducing)

The Reducing method provided by the Collectors class adds support for custom reduction compared to the Reduce method of stream itself.

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); // The sum of each employee's salary minus the threshold Integer sum = personlist.stream ().collect(0, Person::getSalary, (I, class.php). j) -> (i + j - 5000))); System.out.println(" + sum "); // stream reduce Optional<Integer> sum2 = personlist.stream ().map(Person::getSalary).reduce(Integer::sum); System.out.println(" sum2.get() + sum2.get()); }}Copy the code

Running results:

Total employee salary after tax: 8,700 total employee salary: 23,700

3.7 sort (sorted)

Sorted, middle operation. There are two sorts:

  • Sorted () : Sort naturally. Elements in a stream need to implement the Comparable interface
  • Sorted (Comparator com) : The Comparator sorter customizes sorts

Example: Rank employees from highest salary to lowest salary (from oldest to youngest salary)

public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Sherry", 9000, 24, "female", "New York")); personList.add(new Person("Tom", 8900, 22, "male", "Washington")); personList.add(new Person("Jack", 9000, 25, "male", "Washington")); personList.add(new Person("Lily", 8800, 26, "male", "New York")); personList.add(new Person("Alisa", 9000, 26, "female", "New York")); // Sort by salary ascending (natural sort) List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName) .collect(Collectors.toList()); List<String> newList2 = personlist.stream ().sorted(Comparator.comparing(Person::getSalary).reversed()) .map(Person::getName).collect(Collectors.toList()); List<String> newList3 = personlist.stream () .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName) .collect(Collectors.toList()); List<String> newList4 = personlist.stream ().sorted((p1, p2) -> { if (p1.getSalary() == p2.getSalary()) { return p2.getAge() - p1.getAge(); } else { return p2.getSalary() - p1.getSalary(); } }).map(Person::getName).collect(Collectors.toList()); System.out.println(" sort by salary ascending: "+ newList); System.out.println(" sort by salary descending: "+ newList2); System.out.println(" Sort by salary then by age: "+ newList3); System.out.println(" custom descending order by salary then by age: "+ newList4); }}Copy the code

Running results:

[Sherry, Jack, Alisa,Tom, Lily] [Sherry, Jack, Alisa,Tom, Lily] [Sherry, Jack, Alisa, Tom, Lily] [Sherry, Jack, Tom, Lily]

3.8 Extraction/combination

Streams can also be merged, de-duplicated, restricted, and skipped.

public class StreamTest { public static void main(String[] args) { String[] arr1 = { "a", "b", "c", "d" }; String[] arr2 = { "d", "e", "f", "g" }; Stream<String> stream1 = Stream.of(arr1); Stream<String> stream2 = Stream.of(arr2); // concat: Merge two streams distinct: Delete List<String> newList = stream.concat (stream1, stream2).distinct().collect(Collectors. ToList ()); List<Integer> collect = stream.iterate (1, x -> x + 2).limit(10).collect(Collectors. ToList ()); List<Integer> collect2 = stream.iterate (1, x -> x + 2).skip(1).limit(5).collect(Collectors. ToList ()); System.out.println(" stream merge: "+ newList); System.out.println("limit: "+ collect); System.out.println("skip: "+ collect2); }}Copy the code

Running results:

Limit: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] Skip: [3, 5, 7, 9, 11]

4 Stream source code interpretation

Let’s give this part time to break down.

Ok, the above is all content, can insist to see here, you must have a harvest, then move a little hand to take the offer, click “like” and then go.


Author: Cloud deep I do not know the link: blog.csdn.net/mu_wind/art… I will always share Java dry goods, also will share free learning materials courses and interview treasure book reply: [computer] [design mode] have a surprise oh