Preface
The project has been using streams, but it is only a little bit of aware, so I can learn more about it here.
Usually, I will use a few new knowledge of streaming to design Java 8. I will briefly explain these knowledge below, and then learn streams after understanding them or use them more easily.
- Lambda Expressions
- Method reference
- Option
- stream
1. Lambda
It is recommended to understand functional interfaces first
1.1 Syntax
parameter -> expression body;
1.2 There is no parameter and only one statement or multiple statements
()->("baicaizhi"); ()->{ ("baicaizhi1"); ("baicaizhi1"); }
1.3 There is only one statement or multiple statements for a parameter
a->(a); a->{ (a); (a); }
1.4 There is only one statement or multiple statements if multiple parameters are
(a,b)->a+b; (a,b)->{ int c = a+b; (c); }
- Optional parameter type declaration: No need to declare the type of the parameter. The compiler can infer the same value from the value of the parameter.
- Brackets around optional parameters (): If there is only one parameter, the brackets around the parameter can be ignored. But if there are multiple parameters, you must add brackets.
- Optional braces {}: If a Lambda expression contains only one statement, braces can be omitted. But if there are multiple statements, you must add braces.
- Optional return keywords: If the Lambda expression has only one statement, the compiler will automatically return the last result of the statement. But if the return statement is explicitly used, you must add curly braces {}, even if there is only one statement.
2. Method citation
Use: (used when using static methods or new)
Test::new Test::getName
Interface name | Brief description of function |
---|---|
Optional empty() | Build an empty Optional object |
Optional of(T value) | Build a non-empty Optional object, if it is empty, an error will be reported! |
Optional ofNullable(T value) | Build an Optional object, allow empty! |
T get() | Get the value of a generic object. If the value is empty, an error will be reported. |
boolean isPresent() | Query empty, if not null, true |
boolean isEmpty() | Query empty, if null, true |
ifPresent(Consumer) | Pass an interface function pair, and execute this function when the data is not empty |
ifPresentOrElse(Consumer, Runnable) | There are two parameters, the first one is executed when it is not empty, and the second one is executed when it is empty. All are interface functions. |
Optional filter | A filter for an object |
Optional map(Function) | Conversion method |
Optional flatMap(Function) | Conversion method, commonly used to convert one layer with multiple layers |
Optional or(Supplier) | When the object is empty, create a new Optional object based on the interface function |
T orElse(T) | Get a specified generic object when the object is empty |
T orElseThrow() | Not empty Returns the object, if empty, NoSuchElementException |
T orElseThrow(Supplier) | Not empty Returns the object, if empty, specifies an exception |
4.1Stream Overview
4.1.1 What is steam
Stream treats the set of elements to be processed as a stream. During the process of the stream, the elements in the stream are operated on by the Stream API, such as: filtering, sorting, aggregation, etc.
4.1.2Stream can be created by arrays and collections, and convection operations are divided into two categories
4.1.2.1 Intermediate Operation
Each time a new stream is returned, there can be multiple.
4.1.2.2 Terminal operation
Terminal operation, each stream can only perform terminal operation once, and the stream cannot be used again after the terminal operation is completed. Terminal operations will produce a new set or value
4.1.3 Features
Instead of storing data, the data is calculated according to specific rules, and the results are generally output.
The data source does not change, and usually a new set or a value will be generated.
It has the feature of delayed execution, and intermediate operations will only be executed when the terminal operation is called.
3.2Stream creation
3.2.1 Create a stream using the () method
List<String> list = ("a","b","c"); //Create sequential stream Stream<String> stream = (); //Create concurrent stream Stream<String> stringStream = ();
3.2.2 Use the (T[] array) method to create a stream
//Array Creation Stream int[] array = {1,2,3}; IntStream stream1 = (array);
3.2.3 Static methods using Stream: of(), iterate(), generate()
//stream static method creates stream Stream<Integer> integerStream = (1, 2); Stream<Integer> iterate = (0, x -> x = 3); Stream<Double> limit = (Math::random).limit(3);
3.2.4 Convert sequential streams into concurrent streams
//Sequential streams are converted into concurrent streams Optional<String> first = ().parallel().filter(x -> x > 6).findFirst();
4.3 Use
Learn about Optional before using
4.3.1 Data preparation
class Person { private String name; // Name private int salary; // Salary private int age; // age private String sex; //gender private String area; // area // Construct method public Person(String name, int salary, int age,String sex,String area) { = name; = salary; = age; = sex; = area; } // Get and set are omitted, please add it yourself}
4.3.2 Use
4.3.2.1 Traversal/match (foreach/find/match)
Stream also supports traversal and matching elements similar to collections, but the elements in Stream exist in Optional type. Stream traversal and matching is very simple
List<Integer> list = (1,2,3,4,7,6,5,8); // traverse the output elements that meet the criteria ().filter(x->x>6).forEach(::println); // Match the first one Optional<Integer> first = ().filter(x -> x > 6).findFirst(); // Match any (suitable for parallel streams) Optional<Integer> any = ().filter(x -> x > 6).findAny(); // Whether to include elements that meet specific conditions boolean b = ().anyMatch(x -> x < 6); ("Match the first value"+()); ("Match any value"+()); ("Whether there is a value greater than 6"+b);
4.3.2.2 Filter
Filtering is an operation to verify elements in the stream according to certain rules and extract elements that meet the conditions into the new stream.
4.3.2.3 Aggregation (max/min/count)
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); //Filter out elements greater than 7 in the Integer collection and print them out ().filter(x->x>7).forEach(::println); //Screen employees with salary above 8,000 and form a new set. Form a new collection dependency collect (collect) List<String> collect = ().filter(value -> () > 8000).map(Person::getName).collect(()); ("Salary is above 8,000"+collect);
4.3.2.4 Map (map/flatMap)
Mapping, you can map elements of a stream to another stream according to certain mapping rules. It is divided into map and flatMap:
- map: Receive a function as a parameter, which will be applied to each element and map it into a new element.
- flatMap: receives a function as a parameter, swaps each value in the stream for another stream, and then connects all streams into one stream.
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); //All elements of the English string array are changed to capitalization. Integer array +3 per element List<Integer> collect = ().map(x -> x + 3).collect(()); List<String> collect1 = ().map(String::toUpperCase).collect(()); // Increase all employees' salaries by 1,000 //Do not change the way the source collection List<Person> collect2 = ().map(person -> { Person person1 = new Person((), 0, (), (), ()); (() + 1000); return person1; }).collect(()); //Change the way of source collection List<Person> collect3 = ().map(person -> { (() + 1000); return person; }).collect(()); //Combine two character arrays into a new character array List<String> collect4 = ().flatMap(s -> { String[] s2 = (","); return (s2); }).collect(()); ("Each element capitalization:" + collect1); ("Each element +3:" + collect); //Note that the execution is performed separately during execution, otherwise the effect will not be seen. ("Before one change:" + (0).getName() + "-->" + (0).getSalary()); ("After one change:" + (0).getName() + "-->" + (0).getSalary()); ("Before the second change:" + (0).getName() + "-->" + (0).getSalary()); ("After the second change:" + (0).getName() + "-->" + (0).getSalary()); ("Preprocessed collection:" + strList); ("Processed collection:" + collect4);
4.3.2.5 Reduce
Reduction, also known as reduction, as the name implies, is to reduce a stream into a value, which can realize the operation of summing the set, finding the product sum and finding the most value of the set.
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); // Find the sum of the elements, the product sum of the Integer set //Sum method 1 Optional<Integer> reduce = ().reduce((x, y) -> x + y); //Sum method 2 Optional<Integer> reduce1 = ().reduce(Integer::sum); //Sum method 3 Integer reduce2 = ().reduce(0, Integer::sum); // Find the product Optional<Integer> reduce3 = ().reduce((x, y) -> x * y); // Find the maximum value method 1 Optional<Integer> reduce4 = ().reduce((x, y) -> x > y ? x : y); // Find the maximum value writing method 2 Integer reduce5 = ().reduce(1, Integer::max); // Ask for the sum of wages and maximum wages of all employees //Sum method 1 Optional<Integer> reduce7 = ().map(Person::getSalary).reduce(Integer::sum); //Sum method 2 Integer reduce6 = ().reduce(0, (sum, p) -> sum += (),(sum1,sum2)->sum1+sum2); //Sum method 3 Integer reduce8 = ().reduce(0, (sum, p) -> sum += (), Integer::sum); // How to get the maximum salary 1: Integer reduce9 = ().reduce(0, (max, p) -> max > () ? max : (),Integer::max); // How to get the maximum salary 2: Integer reduce10 = ().reduce(0, (max, p) -> max > () ? max : (), (max1, max2) -> max1 > max2 ? max1 : max2); ("list sum:" + () + "," + () + "," + reduce2); ("list finds the source:" + ()); ("List finds the maximum value:" + () + "," + reduce5); ("Sum of wages:" + () + "," + reduce6 + "," + reduce8); ("Maximum wage:" + reduce9 + "," + reduce10);
4.3.2.6 Collect
explain
- collect, collect, can be said to be the most diverse and functional part. Literally, it is to collect a stream, which can eventually be collected into a value or a new set
- Collect mainly depends on the built-in static methods of the class
4.3.2.6.1 Collection (toList/toSet/toMap)
Because the stream does not store data, after the data in the stream is processed, the data in the stream needs to be re-collected into a new set. toList, toSet and toMap are commonly used, and there are also more complex uses such as toCollection and toConcurrentMap.
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); List<Integer> collect = ().filter(x -> x % 2 == 0).collect(()); Set<Integer> collect1 = ().filter(x -> x % 2 == 0).collect(()); Map<String, Person> collect2 = ().filter(p -> () > 8000).collect((Person::getName, p -> p)); ("toList:" + collect); ("toSet:" + collect1); ("toMap:" + collect2);
4.3.2.6.2 Statistics (count/averaging)
Collectors provides a series of static methods for data statistics
- Count: count
- Average: averagingInt, averagingLong, averagingDouble
- Most value: maxBy, minBy
- Summing: summingInt, summingLong, summingDouble
- Statistics all of the above: summarizingInt, summarizingLong, summarizingDouble
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); // Statistics the number of employees, average salary, total salary, maximum salary // Find the total number Long collect = ().collect(()); // Find an average salary Double collect1 = ().collect((Person::getSalary)); // Ask for maximum salary Optional<Integer> collect2 = ().map(Person::getSalary).collect((Integer::compare)); // Ask for the sum of wages Integer collect3 = ().collect((Person::getSalary)); // All information is counted at once DoubleSummaryStatistics collect4 = ().collect((Person::getSalary)); ("Total number of employees:" + collect); ("Average employee salary:" + collect1); ("Sum of employee wages:" + ()); ("All statistics on employee wages:" + collect3);
4.3.2.6.3 Grouping (partitioningBy/groupingBy)
explain
- Partition: Divide the stream into two maps according to conditions, such as whether the salary is higher than 8,000.
- Grouping: Divide the set into multiple maps, such as employees grouping by gender. There are single-level grouping and multi-level grouping.
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); //Divide employees into two parts according to whether their salary is higher than 8,000; group employees by gender and region // Group employees by whether their salary is higher than 8,000 Map<Boolean, List<Person>> collect = ().collect((person -> () > 8000)); // Group employees by gender Map<String, List<Person>> collect1 = ().collect((Person::getSex)); // Group employees by gender first, then by region Map<String, Map<String, List<Person>>> collect2 = ().collect((Person::getSex, (Person::getArea))); ("Whether employees are grouped by salary is greater than 8,000:" + collect); ("Employees are grouped by gender:" + collect1); ("Employee by gender, region:" + collect2);
4.3.2.6.4 Joining
Joining can connect elements in the stream into a string with a specific connector (if not, it is directly connected).
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); //String stitching String collect = ().collect(("-")); //The names of all employees String collect1 = ().map(Person::getName).collect((",")); ("Name of all employees:" + collect1); ("Split string:" + collect);
4.3.2.6.5 Reducing
The reducing method provided by the Collectors class has increased support for custom reduction compared to the reduce method of the stream itself.
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); // The sum of salary after each employee is minus the threshold (this example is not rigorous, but I didn't expect a good example) Integer collect = ().collect((0, Person::getSalary, (i, j) -> i + j - 5000)); ("Sum of employee tax deduction salary:" + collect); // stream's reduce Optional<Integer> reduce = ().map(Person::getSalary).reduce(Integer::sum); ("Sum of employee tax deduction salary:" + ());
4.3.2.7 Sort (sorted)
explain
- sorted(): natural sorting, elements in the stream need to implement the Comparable interface
- sorted(Comparator com): Comparator sorter custom sorting
List<Person> personList = new ArrayList<Person>(); (new Person("Tom", 8900, 11,"male", "New York")); (new Person("Jack", 7000, 12,"male", "Washington")); (new Person("Lily", 7800, 13,"female", "Washington")); (new Person("Anni", 8200, 14,"female", "New York")); (new Person("Owen", 9500, 15,"male", "New York")); (new Person("Alisa", 7900, 16,"female", "New York")); List<Integer> list = (1,2,3,4,7,6,5,8); List<String> strList = ("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd"); // Sort by salary increase order List<String> newList = ().sorted((Person::getSalary)).map(Person::getName) .collect(()); // Sort by salary in reverse order List<String> newList2 = ().sorted((Person::getSalary).reversed()) .map(Person::getName).collect(()); // Order naturally by salary first and then by age (from small to old) List<String> newList3 = ().sorted((Person::getSalary).reversed()) .map(Person::getName).collect(()); // Custom sort by salary first and then by age (from large to small) List<String> newList4 = ().sorted((p1, p2) -> { if (() == ()) { return () - (); } else { return () - (); } }).map(Person::getName).collect(()); ("Sorted by salary:" + newList); ("Sorted by descending wages:" + newList2); ("Sorting naturally by salary first and then by age:" + newList3); ("Sorting by salary first and then by age custom descending order:" + newList4);
4.3.2.8 Extraction/combination (distinct, skip, limit)
The stream can also be merged, deduplicated, restricted, skipped and other operations.
String[] arr1 = { "a", "b", "c", "d" }; String[] arr2 = { "d", "e", "f", "g" }; Stream<String> stream1 = (arr1); Stream<String> stream2 = (arr2); // concat: merge two streams distinct: deduplication List<String> newList = (stream1, stream2).distinct().collect(()); // limit: limit the first n data obtained from the stream List<Integer> collect = (1, x -> x + 2).limit(10).collect(()); // skip: skip the first n data List<Integer> collect2 = (1, x -> x + 2).skip(1).limit(5).collect(()); ("Flow merge:" + newList); ("limit:" + collect); ("skip:" + collect2);
This is the end of this article about the in-depth explanation of Java Stream usage cases. For more related Java Stream content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!