“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”
concept
The set of elements to be processed by a Stream is treated as a Stream. During the flow, the Stream API is used to manipulate the elements in the Stream, such as filtering, sorting, aggregating, and so on.
There are roughly two types of Stream operators: the intermediate operator and the terminating operator
Intermediate operator
In the case of a data flow, the intermediate operator can execute the specified handler, and the data flow can still be passed to the operator at the next level.
There are eight intermediate operators (excluding parallel and sequential, which do not involve processing streams of data) :
- Map (mapToInt mapToLong, mapToDouble) conversion operators, such as A – > B, the default here provides an int, long, double operators.
- Flatmap (flatmapToInt flatmapToLong, flatmapToDouble) the pat down operations such as int [] {4} 2 pat down into 2 and 4 is one from the original data into three, By default, int,long, and double are provided.
- If there are 10 streams in a stream, I can use the first 3 streams.
- Distint deduplicating: Deduplicating elements using equals ().
- Filter Indicates the operation of filtering unwanted data.
- Peek pick out operation, if you want to perform some operation on the data, such as: read, edit, modify, etc.
- Skip the operation. Skip some elements.
- Sorted (unordered) sorting operation, the sequence of elements, the premise is to implement the Comparable interface, of course, can also customize the comparator.
Terminate operator
After the data is processed, it’s the end operator’s turn;
The terminating operator is used to collect or consume data. Data does not flow down to the terminating operator. The terminating operator can only be used once.
- Collect Collects all data. This operation is very important. Official Collectors provide a large number of Collectors.
- Count Indicates the number of data to be counted.
- FindFirst, findAny, find the first, findAny return type is Optional.
- NoneMatch, allMatch, anyMatch: indicates whether there are elements matching the conditions in the data stream. The returned value is bool.
- Min and Max operations require custom comparators to return the maximum and minimum values in the data stream.
- Reduce reduces the value of the entire data flow to a value. For example, count, min, and Max are reduced.
- ForEach, forEachOrdered traversal, where the final data is consumed.
- The toArray operation converts the elements of a data stream into an array.
The creation of a Stream
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
Stream<String> stream = list.stream();
// Create a parallel stream
Stream<String> parallelStream = list.parallelStream();
Copy the code
Create a stream from Arrays using the java.util.arrays.stream (T[] array) method
int[] array={1.3.5.6.8};
IntStream stream = Arrays.stream(array);
Copy the code
Iterate (), iterate(), generate(), iterate()
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 3 6 9
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);
Copy the code
Output results:
3
6
9
0.8106623442686114
0.11554643727388458
0.1404645961428974
Process finished with exit code 0
Copy the code
Simple distinction between stream and parallelStream:
Stream is a sequential stream, and the main thread performs operations on the stream in sequence; ParallelStream is a parallelStream that operates internally on streams in a manner that allows multiple threads to execute in parallel, but only if there is no order required for data processing in the stream.
For example, to filter odd numbers in a set, the processing of the two is different:
The Stream to use
Iterating/matching (foreach/find/match)
Stream also supports iterating over and matching elements like collections, but the elements in a Stream are Optional. Stream traversal and matching are very simple.
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7.6.9.3.8.2.1);
// Iterate over the elements that output the condition
list.stream().filter(x -> x > 6).forEach(System.out::println);
// Match the first one
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();
// Whether to include elements that meet certain conditions
boolean anyMatch = list.stream().anyMatch(x -> x < 6);
System.out.println("Match the 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
Output results:
7 9 8 Match the first value: 7 Match any value: 8 Check whether values greater than 6 exist: true Process Finished with exit code 0Copy the code
Filter
Filtering is an operation that verifies the elements in the flow according to certain rules and extracts the elements that meet the conditions into the new flow.
selectInteger
All the elements greater than 7 in the set, and print them 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
Output results:
8
9
Process finished with exit code 0
Copy the code
Polymerization (Max/min/count)
The words Max, min, and count are familiar to you, yes, we use them for data statistics in mysql. Java Stream also introduces these concepts and usage, greatly facilitates our collection, array data statistics work.
Case 1: AcquisitionString
The 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 results:
Longest string: weoujgSD Process Finished with exit code 0Copy the code
Case 2: AcquisitionInteger
The 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 ordering
Optional<Integer> max = list.stream().max(Integer::compareTo);
// Custom sort
Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
returno1.compareTo(o2); }}); System.out.println("Maximum natural ordering:" + max.get());
System.out.println("Maximum value of a custom sort:"+ max2.get()); }}Copy the code
Output results:
Maximum value of natural sorting: 11 Maximum value of custom sorting: 11 Process Finished with exit code 0Copy the code
Case 3: CalculationInteger
The number of elements greater than 6 in a set.
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 greater than 6 in list:"+ count); }}Copy the code
Output results:
Number of elements greater than 6 in the list: 4 Process Finished with exit code 0Copy the code
Mapping (map/flatMap)
Mapping, which maps elements of one stream to another according to certain mapping rules. There are 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 a parameter, replaces each value in the stream with another, and concatenates all streams into one.
Example 1: Change all elements of an English string array to uppercase. Each element of an integer array is plus 3.
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());
System.out.println(Capitalize each element: + strList);
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("+3 per element:"+ intListNew); }}Copy the code
Output results:
Each element capital: [ABCD, BCDD, DEFDE, FTR] Each element +3: [4, 6, 8, 10, 12, 14] Process Finished with exit code 0Copy the code
Case 2: Merge 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("Collection before processing:" + list);
System.out.println("Processed collection:"+ listNew); }}Copy the code
Output results:
[m, K, L,a, 1,3,5,7] Process finished with exit code 0Copy the code
Reduction (reduce)
Reduction, also known as reduction, is the reduction of a stream to a value that enables summing, multiplying, and maximizing the set.
Case 1: begInteger
The sum, product, and maximum 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);
// Summation 1
Optional<Integer> sum = list.stream().reduce(Integer::sum);
// Summation 2
Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
// Summation 3
Integer sum3 = list.stream().reduce(0, Integer::sum);
/ / product
Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
// Obtain the maximum value in method 1
Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
// To find the maximum value, write method 2
Integer max2 = list.stream().reduce(1, Integer::max);
System.out.println("List sum:" + sum.get() + "," + sum2.get() + "," + sum3);
System.out.println("List quadrature:" + product.get());
System.out.println("List sum:" + max.get() + ","+ max2); }}Copy the code
Output results:
List summation: 29,29,29 list quadrature: 2112 list summation: 11,11 Process finished with exit code 0Copy the code
The collection (toList/toSet/toMap)
Because streams do not store data, the data in the stream needs to be reassembled into new collections after the data in the stream is processed. ToList, toSet and toMap are more commonly used, in addition to toCollection, toConcurrentMap and other more complex uses.
Here’s an example of toList, toSet, and toMap:
public class Person {
private String name; / / name
private int salary; / / salary
private int age; / / age
private String sex; / / gender
private String area; / / region
// The constructor
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;
}
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary(a) {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getAge(a) {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex(a) {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getArea(a) {
return area;
}
public void setArea(String area) {
this.area = area;
}
@Override
public String toString(a) {
return "Person{" +
"name='" + name + '\' ' +
", salary=" + salary +
", age=" + age +
", sex='" + sex + '\' ' +
", area='" + area + '\' ' +
'} '; }}Copy the code
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
Output results:
toList:[6, 4, 6, 6, 20]
toSet:[4, 20, 6]
toMap:{Tom=Person{name='Tom', salary=8900, age=23, sex='male', area='New York'}, Anni=Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}}
Process finished with exit code 0
Copy the code
Statistics (count/averaging)
Collectors provides a set of static methods for data statistics:
- Count:
count
- Average:
averagingInt
,averagingLong
,averagingDouble
- The most value:
maxBy
,minBy
- Sum:
summingInt
,summingLong
,summingDouble
- Statistics all above:
summarizingInt
,summarizingLong
,summarizingDouble
Case: Count the number of employees, average salary, total salary, 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"));
/ / the total number
long count = personList.size();
// Ask for the average salary
Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
// Ask for the highest salary
Optional<Integer> max = personList.stream().map(Person::getSalary).max(Integer::compare);
// Sum of wages
int sum = personList.stream().mapToInt(Person::getSalary).sum();
// Count all information at once
DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println("Number of employees:" + count);
System.out.println("Average salary of employees:" + average);
System.out.println("Maximum employee salary:" + max.get());
System.out.println("Total wages of employees:" + sum);
System.out.println("Employee salary all statistics:"+ collect); }}Copy the code
Output results:
Total employees: 3 Average salary of employees: 7900.0 Highest salary of employees: 8,900 Total salary of Employees: 23,700 All statistics: DoubleSummaryStatistics {count = 3, the sum = 23700.000000, min = 7000.000000, business = 7900.000000, Max =8900.000000} Process Finished with exit code 0Copy the code
Group (partitioningBy/groupingBy)
- Partition:
stream
According to the condition divided into twoMap
For example, employees are divided into two parts according to whether the salary is higher than 8000. - Grouping: Divide the collection into multiple Maps, such as grouping employees by gender. There are single-level grouping and multilevel grouping.
Case: The employee is divided into two parts according to whether the 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.23."male"."Washington"));
personList.add(new Person("Jack".7000.25."male"."Washington"));
personList.add(new Person("Lily".7800.21."female"."New York"));
personList.add(new Person("Anni".8200.24."female"."New York"));
// Group employees according to whether their salary is higher than 8000
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
// Group employees by gender
Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
// Group employees first by gender and then by region
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println("Employees are grouped according to whether their salary is greater than 8000:" + part);
System.out.println("Group of employees by gender:" + group);
System.out.println("Employees by gender, region:"+ group2); }}Copy the code
Output results:
Group of employees according to whether the salary is greater than 8000: {false=[Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}, Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}], true=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}]} {female=[Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}], male=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}] {female={New York=[Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}]}, male={Washington=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}]}} Process finished with exit code 0Copy the code
Joint (joining)
Joining concatenates elements in stream into a string with a specific concatenation (or direct concatenation if not available).
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(Person::getName).collect(Collectors.joining(","));
System.out.println("Name 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
Output results:
All employee names: Tom,Jack,Lily String: A-B-c Process Finished with exit code 0Copy the code
Sorting (sorted)
Sorted, intermediate operation. There are two kinds of sorting:
sorted()
: Natural ordering, which elements in the stream need to implementComparable
interfacesorted(Comparator com)
:Comparator
Collator custom sort
Case study: Rank employees by salary from highest to lowest (and by age from highest to lowest for the same 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"));
// Order in ascending order (natural order)
List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
.collect(Collectors.toList());
// In reverse order of salary
List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName).collect(Collectors.toList());
// Order by salary first and then by age
List<String> newList3 = personList.stream()
.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
.collect(Collectors.toList());
// Order by salary and then by age
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("In ascending order of pay:" + newList);
System.out.println("In descending order of pay:" + newList2);
System.out.println("Rank by salary first and then ascending by age:" + newList3);
System.out.println("Rank by salary first and then custom descending by age:"+ newList4); }}Copy the code
Output results:
Order by salary: [Lily, Tom, Sherry, Jack, Alisa] Order by salary: [Lily, Tom, Sherry, Jack, Alisa] Process finished with exit code 0Copy the code
Extraction/combination
Streams can also be merged, deduplicated, restricted, or 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: merges two streams distinct: deduplicates
List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
// limit: limits the first n data to be obtained from the stream
List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
// skip: skip the first n data
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
Output results:
[a, B, C, D, E, f, g] LIMIT: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] [3, 5, 7, 9, 11] Process finished with exit code 0Copy the code
paging
The power of the STREAM API goes beyond the various combinations of collections to support paging.
For example, sort the following array from small to large. After sorting, query 10 items of data from the first row. The operation is as follows:
// The data to be queried
List<Integer> numbers = Arrays.asList(3.2.2.3.7.3.5.10.6.20.30.40.50.60.100);
List<Integer> dataList = numbers.stream().sorted(Integer::compareTo).skip(0).limit(10).collect(Collectors.toList());
System.out.println(dataList.toString());
Copy the code
Output results:
[2, 2, 3, 3, 3, 5, 6, 7, 10, 20]
Process finished with exit code 0
Copy the code
Parallel operation
The so-called parallel, refers to multiple tasks at the same point in time, and by different CPUS for processing, do not preempt each other resources; Concurrency, on the other hand, refers to multiple tasks occurring simultaneously at the same time, but being processed by the same CPU, which preempts resources from each other.
For example, we use parallelStream to output the number of empty strings:
List<String> strings = Arrays.asList("abc".""."bc"."efg"."abcd".""."jkl");
// Get the number of empty strings using parallel computation
long count = strings.parallelStream().filter(String::isEmpty).count();
System.out.println(count);
Copy the code
In actual use,Parallel operation
Not necessarily better thanSerial operation
Come on! For simple operations, the number is very large, and the server is multi-core, it is recommended to use Stream parallel! On the contrary, serial operation is more reliable!
Set to Map operation
In the actual development process, one of the most frequently used operations is to use a primary key field in the set element as the key and the element as the value to realize the requirement of converting the set to a map. This requirement is widely used in data assembly.
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom".7000.25."male"."Anhui province"));
personList.add(new Person("Jack".8000.30."female"."Beijing"));
personList.add(new Person("Lucy".9000.40."male"."Shanghai"));
personList.add(new Person("Airs".10000.40."female"."Shenzhen"));
Map<Integer, Person> collect = personList.stream().collect(Collectors.toMap(Person::getAge, v -> v, (k1, k2) -> k1));
System.out.println(collect);
}
Copy the code
Output results:
{40=Person{name='Lucy', salary=9000, age=40, sex='male', area=' Shanghai '}, 25=Person{name='Tom', salary=7000, age=25, Sex ='male', area=' anhui '}, 30=Person{name='Jack', salary=8000, age=30, sex='female', Area =' Beijing '}} Process finished with exit code 0Copy the code
Open the oughter.tomap method source code and take a look.
public static<T, K, U> Collector<T, ? , Map<K,U>> toMap(Function<?super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
Copy the code
As can be seen from the parameter table:
- The first parameter: key
- The second parameter: represents value
- The third parameter: represents some kind of rule
The Collectors. ToMap (Person::getAge, v -> v, (k1,k2) -> k1), which means that the content of age is the key, v -> v means that the element Person is the value. Where (k1,k2) -> k1 means that if there is the same key, the first matching element will be the content, and the second one will be discarded!
At the end
This article mainly focuses on JDK STREAM API operation, combined with the actual daily development needs, made a simple summary and share. I hope you can also follow along with the tap to deepen the impression, I believe you can master the initial use of these operators; In subsequent articles, I’ll take you step by step into Stream. I hope you can give me a thumbs up. Haha.