Make Java8 Stream easier
I believe that many little partners of programmers who have just entered the pit are very headache by some code, which makes us feel both familiar and unfamiliar. Many of our new friends are more used to using for loops or iterators to solve some traversal problems, but many old people in the company like to use Stream flow, a new feature of Java 8, so that the requirements can be realized in shorter code, but it is less readable for unfamiliar novices.
1. Why do experienced veterans prefer to use Stream
- Performance advantages, (large amount of data) faster than iterators
- Support serial and parallel processing, and parallel processing can make full use of CPU resources
- A Stream is a Stream that calculates data and does not store data itself
- Support functional programming
- Elegant code makes the code more efficient, clean and concise
2. Usage of stream
Three steps:
- Create Stream
- Intermediate operation
- Terminate operation
3. Creation of stream
The creation of a Stream depends on the data source, usually a container or array
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; public class CreateStreamDemo { public static void main(String[] args) { // 1 creating a Stream through a collection is also the most used form List<String> strList = new ArrayList<>(); strList.add("a"); strList.add("b"); strList.add("c"); // Create serial operation flow Stream<String> stream = strList.stream(); // Create parallel operation flow Stream<String> parallelStream = strList.parallelStream(); // 2 create a Stream from an array int[] arr = new int[]{1,2,3}; IntStream intStream = Arrays.stream(arr); // 3 through Stream.of Stream<Integer> integerStream = Stream.of(1,2,3); Stream<String> stringStream = Stream.of("a","b","c"); // 4 infinite flow // Take one every five numbers Stream.iterate(0, t -> t + 5).forEach(System.out::println); // iteration Stream.generate(Math::random).forEach(System.out::println); // generate } }
4. Stream intermediate operation
import com.zhj.java8.bean.Student; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.TreeSet; import java.util.stream.Stream; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; public class MiddleStreamDemo { public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student(1,"Xiaohua",23,1)); students.add(new Student(1,"Xiaohua",23,2)); students.add(new Student(2,"millet",20,2)); students.add(new Student(3,"Small fruit",30,3)); students.add(new Student(4,"Xiao Wei",18,2)); // filter students.stream().filter(stu -> stu.getAge() > 20).forEach(System.out::println); // duplicate removal // The object de duplication is based on the reference, and the repeated content will not be de duplicated unless the equals and hashCode methods are overridden System.out.println("----------duplicate removal----------"); System.out.println("Weight removal 1----------"); students.stream().distinct().forEach(System.out::println); // For the de duplication of some attributes of objects in the collection, the equals and hashCode methods are not rewritten, but can only be assisted by other data structures // A single attribute can be stu - > stu. Getid() // Multiple attributes can be stu - > stu. Getid() + ";" + stu. Getname() System.out.println("Weight removal 2----------"); ArrayList<Student> distinctList = students.stream().collect( collectingAndThen(toCollection(() -> new TreeSet<>(Comparator.comparing(stu -> stu.getId() + ";" + stu.getName()))), ArrayList::new) ); distinctList.stream().forEach(System.out::println); // Sorting supports defining sorting methods // sorted uses natural ordering by default, and its elements must implement the Comparable interface System.out.println("----------sort----------"); System.out.println("Sort 1----------"); students.stream().sorted().forEach(System.out::println); // Sorted (Comparator <? Super T > Comparator): we can use lambada to create a Comparator instance. You can sort elements in ascending or descending order. System.out.println("Sort 2----------"); students.stream() .sorted(Comparator.comparing(Student::getAge,Comparator.reverseOrder())) // , Comparator.reverseOrder() .forEach(System.out::println); // Create a comparator and sort multiple attributes through the definition of comparator content, which is similar to the continuous orderBy in sql System.out.println("Sort 3----------"); students.stream().sorted( (s1,s2) -> { if (s1.getAge() == s2.getAge()) { return s1.getSex().compareTo(s2.getSex()); } else { return -s1.getAge().compareTo(s2.getAge()); } } ).forEach(System.out::println); System.out.println("Sort 4----------"); Comparator<Student> studentComparator = (s1,s2) -> { Integer age1 = s1.getAge(); Integer age2 = s2.getAge(); if (age1 != age2) return age1 - age2; Integer sex1 = s1.getSex(); Integer sex2 = s2.getSex(); if (sex1 != sex2) return sex2 - sex1; return 0; }; students.stream().sorted(studentComparator).forEach(System.out::println); // Intercept the first three elements System.out.println("----------intercept----------"); students.stream().limit(3).forEach(System.out::println); // Skip the first 3 elements System.out.println("----------skip----------"); students.stream().skip(3).forEach(System.out::println); // mapping System.out.println("----------mapping----------"); System.out.println("mapping Map----------"); // map receives Lambda, converts elements into other forms, or extracts information and maps it into a new element Stream<Stream<Student>> streamStream1 = students.stream().map(str -> filterStudent(str)); streamStream1.forEach(sm -> sm.forEach(System.out::println)); System.out.println("mapping flatMap----------"); // Map receives Lambda, converts each element in the stream into another stream, and then connects all streams into a stream flattening map Stream<Student> studentStream2 = students.stream().flatMap(str -> filterStudent(str)); studentStream2.forEach(System.out::println); // consumption System.out.println("----------consumption----------"); students.stream().peek(stu -> stu.setAge(100)).forEach(System.out::println); } public static Stream<Student> filterStudent(Student student) { student = new Student(); return Stream.of(student); } }
Student
public class Student implements Comparable<Student> { private Integer id; private String name; private Integer age; private Integer sex; public Student() { } public Student(Integer id, String name, Integer age, Integer sex) { this.id = id; this.name = name; this.age = age; this.sex = sex; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } @Override public String toString() { return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age='" + age + '\'' + ", sex=" + sex + '}'; } @Override public int compareTo(Student o) { return this.getAge() - o.getAge(); } }
5. Stream termination
package com.zhj.java8.stream; import com.zhj.java8.bean.Student; import java.util.*; import java.util.stream.Collectors; public class TerminationStreamDemo { public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student(1,"Xiaohua",23,1)); students.add(new Student(2,"millet",20,2)); students.add(new Student(3,"Small fruit",30,3)); students.add(new Student(4,"Xiao Wei",18,2)); students.add(new Student(5,"Xiaohua",23,2)); System.out.println("--------------------Match aggregation operation--------------------"); // allMatch: receives a Predicate function. It returns true only when each element in the stream conforms to the assertion. Otherwise, it returns false boolean allMatch = students.stream().allMatch(stu -> stu.getAge() > 10); System.out.println("All meet the conditions of over 10 years old:" + allMatch); // noneMatch: receives a Predicate function. It returns true only when every element in the stream does not conform to the assertion. Otherwise, it returns false boolean noneMatch = students.stream().noneMatch(stu -> stu.getAge() > 10); System.out.println("All of them do not meet the conditions of being over 10 years old:" + noneMatch); // anyMatch: receives a Predicate function. As long as an element in the stream satisfies the assertion, it returns true; otherwise, it returns false boolean anyMatch = students.stream().anyMatch(stu -> stu.getAge() > 20); System.out.println("Contains any of the following:" + anyMatch); // findFirst: returns the first element in the stream Student findFirst = students.stream().findFirst().get(); System.out.println("First student:" + findFirst); // findAny: returns any element in the stream Student findAny = students.stream().findAny().get(); System.out.println("Any student:" + findAny); // count: returns the total number of elements in the stream long count = students.stream().count(); System.out.println("Total number of students:" + count); // max: returns the maximum value of the element in the stream Student max = students.stream().max(Student::compareTo).get(); System.out.println("Oldest student:" + max); // max: returns the maximum value of the element in the stream Student min = students.stream().min(Student::compareTo).get(); System.out.println("Youngest student:" + min); System.out.println("--------------------Protocol operation--------------------"); System.out.println("Total student age:" + students.stream().map(Student::getAge).reduce(Integer::sum)); System.out.println("Maximum student age:" + students.stream().map(Student::getAge).reduce(Integer::max)); System.out.println("--------------------Collection operation--------------------"); List<Student> list = students.stream().collect(Collectors.toList()); Set<Student> set = students.stream().collect(Collectors.toSet()); Map<Integer, String> map = students.stream().collect(Collectors.toMap(Student::getId, Student::getName)); String joinName = students.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")")); // total students.stream().collect(Collectors.counting()); // Maximum age students.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get(); // Age and students.stream().collect(Collectors.summingInt(Student::getAge)); // average age students.stream().collect(Collectors.averagingDouble(Student::getAge)); // Information collection DoubleSummaryStatistics statistics = students.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>> collect = students.stream().collect(Collectors.groupingBy(Student::getSex)); System.out.println(collect); //Multiple grouping, first according to gender and then according to age Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAge))); //partition //It is divided into two parts, one is older than 20 years old and the other is less than or equal to 20 years old Map<Boolean, List<Student>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 20)); //Statute Integer allAge = list.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get(); System.out.println(allAge); } }
6. Stream characteristics
-
Inert execution of intermediate operation
If there are multiple intermediate operations, there will be no multiple cycles. Multiple conversion operations will only be merged when the operation is terminated, and the cycle will be completed at one time.
-
Internal iteration
-
The iteration after finding the qualified data will not proceed
-
The end of the stream is operated only once
Exception: stream has already been operated upon or closed
This means that the flow has been closed, because when we use the end operation, the flow is closed and cannot be called again. If we want to call again, we can only reopen a new flow.