Two major changes in Java 8 are Lambda expressions and Stream API expressions. Stream is a key abstract concept for processing sets in Java 8. It can perform very complex operations such as searching, filtering and filtering on sets. Stream has also been added to the new version of JPA [connect database].
Stream API brings us powerful functions to operate the collection. At the same time, stream API is simple and easy to use.
for example
@Query("select u from User u") Stream<User> findAllByCustomQueryAndStream(); Stream<User> readAllByFirstnameNotNull(); @Query("select u from User u") Stream<User> streamAllPaged(Pageable pageable);
Operation steps of Stream
Stream has the following three operation steps:
1, Create Stream
Get a stream from a data source, such as a collection or array.
2, Intermediate operation
An intermediate chain of operations, which operates on the data of the data source.
3, Terminate operation
A termination operation that executes an intermediate chain of operations and produces results.
Note: after the convection operation is completed, it needs to be turned off
Take a simple example:
Suppose there is a Person class and a Person list. Now there are two requirements: 1) find people older than 18 and output them; 2) Find out the number of all Chinese.
@Data class Person { private String name; private Integer age; private String country; private char sex; public Person(String name, Integer age, String country, char sex) { this.name = name; this.age = age; this.country = country; this.sex = sex; } }
List<Person> personList = new ArrayList<>(); personList.add(new Person("Ouyang Xue",18,"China",'F')); personList.add(new Person("Tom",24,"U.S.A",'M')); personList.add(new Person("Harley",22,"britain",'F')); personList.add(new Person("Smile to the sky",20,"China",'M')); personList.add(new Person("Kang Li",22,"China",'M')); personList.add(new Person("Xiaomei",20,"China",'F')); personList.add(new Person("He Xue",21,"China",'F')); personList.add(new Person("Kang Li",22,"China",'M'));
Before JDK8, we can complete it by traversing the list. However, with the Stream API, it can be implemented as follows:
public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("Ouyang Xue", 18, "China", 'F')); personList.add(new Person("Tom", 24, "U.S.A", 'M')); personList.add(new Person("Harley", 22, "britain", 'F')); personList.add(new Person("Smile to the sky", 20, "China", 'M')); personList.add(new Person("Kang Li", 22, "China", 'M')); personList.add(new Person("Xiaomei", 20, "China", 'F')); personList.add(new Person("He Xue", 21, "China", 'F')); personList.add(new Person("Kang Li", 22, "China", 'M')); // 1) Find people older than 18 and output them; //Create stream object Boolean test (T); void accept(T t); personList.stream().filter(t->t.getAge()>20).forEach(t->System.out.println(t)); // Method reference in lamdba personList.stream().filter(t->t.getAge()>20).forEach(System.out::println); // 2) Find out the number of all Chinese. count() calculate quantity long c = personList.stream().filter(t -> t.getCountry().equals("China")).count(); System.out.println(c); }
In this example, personlist Stream () is to create a stream, filter() is an intermediate operation, and forEach and count() are termination operations.
Stream intermediate operation – filter and slice parallel streams with parallelStream
filter: receive Landba and exclude some operations from the stream
limit: truncate the stream so that its elements do not exceed the given object
Skip (n): skip elements and return a stream that discards the first n elements. If there are less than n elements in the stream, an empty stream will be returned, which is complementary to limit (n)
distinct: filter to remove duplicate elements through hashCode () and equals () of the elements generated by the stream.
limit example
Demand, take two women from the Person list.
// Take two women from the Person list. limit personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println);
skip example
Start with the second woman in the Person list and take out all women.
// Start with the second woman in the Person list and take out all women. skip(1) means skip the first one personList.stream().filter(t->t.getSex()=='F').skip(1).forEach(System.out::println);
distinct example
// duplicate removal personList.stream().distinct().forEach(System.out::println);
Stream intermediate operation - mapping
- map – receive Lambda, convert elements into other forms or extract information. Receive a function as an argument, which will be applied to each element and mapped to a new element.
- flatMap – take a function as a parameter, change each value in the stream into another stream, and then connect all streams into one stream
map example
For example, we use a PersonCountry class to receive all country information
// For example, we use a PersonCountry class to receive all country information r apply (T); personList.stream().map(t->t.getCountry()).forEach(System.out::println);
Receiving all names and countries first encapsulates an entity class with two fields
// Receiving all names and countries first encapsulates an entity class with two fields personList.stream().map(t->new NameAndCountry(t.getName(),t.getCountry())).forEach(System.out::println);
@Data @AllArgsConstructor @NoArgsConstructor class NameAndCountry{ private String name; private String country; }
Sort the previous personList according to the age from small to large. If the age is the same, then sort by name
//Sort the previous personList according to the age from small to large. If the age is the same, then sort by name //This class must be used to implement natural sorting // personList.stream().sorted(); // int compare(T o1, T o2); // The first method personList.stream().sorted((o1, o2) -> { if (o1.getAge() == o2.getAge()) { return o1.getName().compareTo(o2.getName()); } return o1.getAge() - o2.getAge(); }).forEach(System.out::println); System.out.println("-----------------"); //The second method uses the ternary operator personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println);
summary
1. filter(Predicate) 2. limit(long) 3. skip(long) 4. distinct(); 5. map(Function) 6. sorted() | sorted(Comparator)
Terminate operation – find and match
- allMatch – check to see if all elements match
- anyMatch – check to see if at least one element matches
- noneMatch – check if all elements are not matched
- findFirst – returns the first element
- findAny – returns any element in the current stream
- count – returns the total number of elements in the stream
- max – returns the maximum value in the stream
- min – returns the minimum value in the stream
These aspects are described in the Stream class. Here are not examples one by one, but only one example of allMatch and max.
allMatch checks whether at least one element is matched
Determine whether all the people in the personList are over 18 years old
//Check to see if at least one element matches boolean b = personList.stream().anyMatch(item -> item.getAge() >18); System.out.println(b);
Determine whether all the people in the personList are adults
// Judge whether all the people in the personList are Chinese: boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("China")); System.out.println(b1);
findAny returns any element in the current stream
//Returns any element in the current stream Optional<Person> any = personList.stream().findAny(); System.out.println(any); //Returns any element in the current stream // Person person = personList.stream().findAny().get(); Person person = personList.parallelStream().findAny().get(); System.out.println(person);
max - returns the maximum value in the stream
Find the oldest in the personList
// Find the oldest int compare(T o1, T o2); Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge()); System.out.println(max);
reduction
The reduction operation of Stream API can repeatedly combine the elements in the stream to obtain a value, including
Optional<T> reduce(BinaryOperator<T> accumulator); T reduce(T identity, BinaryOperator<T> accumulator); <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
Find a sum of 1 to 100
First method:
The second method of reduce is used: t reduce (t identity, binary operator accumulator)
// Find the sum protocol of 1-100 List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(new Random().nextInt(10)); } System.out.println(list); // R apply(T t, T u,T r); Optional<Integer> reduce = list.stream().reduce((t, u) -> t + u); System.out.println(reduce);
Disassemble this action, and its operation steps are simulated as follows:
0 (1,2) -> 1 + 2 + 0
3 (3,4) -> 3 + 4 + 3
10 (5,6) -> 5 + 6 + 10
The operation step is to add the two elements of the list each time, and accumulate the result with the addition result of the previous two elements. Therefore, at the beginning, set the identity to 0, because the first element and the second element have not been operated before when they are added
The second method:
Integer[] list = {1, 2, 3, 4, 5}; System.out.println(Arrays.asList(list)); Arrays.stream(list).reduce((t,u)->{ System.out.println(t+"-----"+u); return t+u; }); System.out.println(Arrays.asList(list));
Ask for the sum of all people's ages
// Ask for the sum of all people's ages Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u); System.out.println(reduce);
Find the average age of everyone
Collectors.averagingDouble
//averagingDouble Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge())); System.out.println(collect1);
Find the set of all people's ages
collect(Collectors.toList())
List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList());
Find the maximum age of everyone in the set
// Find the maximum age in the set Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect2);
Minimum age type.
There are other operations, you can refer to Java util. stream. Collectors.
Pay attention to the closure of the flow
Find the minimum age of everyone in the set.
try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) { final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo)); System.out.println(minAge.get()); }
It is better to put the stream operation in try with resources. For convenience, the previous content in this chapter is not put in try with resources.
Complete test code
package com.zz.lamdab.lamdba04; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Stream; public class Deom1 { public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("Ouyang Xue", 18, "China", 'F')); personList.add(new Person("Tom", 24, "U.S.A", 'M')); personList.add(new Person("Harley", 22, "britain", 'F')); personList.add(new Person("Smile to the sky", 20, "China", 'M')); personList.add(new Person("Kang Li", 22, "China", 'M')); personList.add(new Person("Xiaomei", 20, "China", 'F')); personList.add(new Person("He Xue", 21, "China", 'F')); personList.add(new Person("Kang Li", 22, "China", 'M')); // 1) Find people older than 18 and output them; //Create stream object Boolean test (T); void accept(T t); personList.stream().filter(t -> t.getAge() > 20).forEach(t -> System.out.println(t)); // Method reference in lamdba personList.stream().filter(t -> t.getAge() > 20).forEach(System.out::println); // 2) Find out the number of all Chinese. count() calculate quantity long c = personList.stream().filter(t -> t.getCountry().equals("China")).count(); System.out.println(c); // Take two women from the Person list. limit personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println); // Start with the second woman in the Person list and take out all women. skip(1) means skip the first one personList.stream().filter(t -> t.getSex() == 'F').skip(1).forEach(System.out::println); System.out.println("-----------------"); // duplicate removal personList.stream().distinct().forEach(System.out::println); System.out.println("-----------------"); // For example, we use a PersonCountry class to receive all country information r apply (T); personList.stream().map(t -> t.getCountry()).forEach(System.out::println); // Receiving all names and countries first encapsulates an entity class with two fields personList.stream().map(t -> new NameAndCountry(t.getName(), t.getCountry())).forEach(System.out::println); System.out.println("-----------------"); //Sort the previous personList according to the age from small to large. If the age is the same, then sort by name //This class must be used to implement natural sorting // personList.stream().sorted(); // int compare(T o1, T o2); // The first method personList.stream().sorted((o1, o2) -> { if (o1.getAge() == o2.getAge()) { return o1.getName().compareTo(o2.getName()); } return o1.getAge() - o2.getAge(); }).forEach(System.out::println); System.out.println("-----------------"); //The second method uses the ternary operator personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println); System.out.println("-----------------"); //Returns any element in the current stream Optional<Person> any = personList.stream().findAny(); System.out.println(any); System.out.println("-----------------"); // Check to see if at least one element matches boolean b = personList.stream().anyMatch(item -> item.getAge() >18); System.out.println(b); // Judge whether all the people in the personList are Chinese: boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("China")); System.out.println(b1); //Returns any element in the current stream // Person person = personList.stream().findAny().get(); Person person = personList.parallelStream().findAny().get(); System.out.println(person); // Find the oldest int compare(T o1, T o2); Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge()); System.out.println(max); // Ask for the sum of all people's ages Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u); System.out.println(reduce); List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList()); //averagingDouble Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge())); System.out.println(collect); System.out.println(collect1); // Find the maximum age in the set Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect2); // Pay attention to the closure of the flow // Stream<Integer> integerStream = personList.stream().map(Person::getAge); try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) { final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo)); System.out.println(minAge.get()); } } } @Data class Person { private String name; private Integer age; private String country; private char sex; public Person(String name, Integer age, String country, char sex) { this.name = name; this.age = age; this.country = country; this.sex = sex; } } @Data @AllArgsConstructor @NoArgsConstructor class NameAndCountry { private String name; private String country; }