Stream stream
Three operation steps of Stream
- Create Stream
- Intermediate operation
- Terminate operation (terminal operation)
Create Stream
Four ways to create a stream
- The stream() method or parallelStream() provided through the Collection series Collection
List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); Stream<String> stream2 = list.parallelStream();
- Get an array stream through a static method
Employee[] employees = new Employee[10]; Stream<Employee> stream2 = Arrays.stream(employees);
- Through the of method in the static class of Stream class
Stream<String> stream3 = Stream.of("aa","bb","cc","dd");
- Create infinite flow: two (iteration and generation)
// 4.1 iteration: pass a starting value and a unary operation Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2); ///Intermediate operation termination operation stream4.limit(10).forEach(System.out::println); // 4.2 generation (infinite generation of random numbers) Stream.generate(()->Math.random()).forEach(System.out::println);
Intermediate operation
Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation"
1. Screening and slicing
method | describe |
---|---|
filter | Receive Lambda and exclude some elements from the stream |
limit | Truncate the flow so that its elements do not exceed the given number |
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 is returned, which is complementary to limit(n) |
distinct | Filter and remove duplicate elements through hashCode() and equals() of the elements generated by the flow |
example:
- Employee object
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode() public class Employee { private int id; private String name; private int age; private double salary; private Status status; public enum Status { BUSY,FREE,VOCATION; } public Employee(int id, String name, int age, double salary) { this.id = id; this.name = name; this.age = age; this.salary = salary; } }
1.1 filter: filter
List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11), new Employee(2, "Li Si", 49, 2222.22), new Employee(3, "Zhao Liu", 57, 3333.33), new Employee(4, "pseudo-ginseng", 35, 4444.44), new Employee(4, "pseudo-ginseng", 35, 4444.44) ); /** * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation" * 1.Filtering and slicing: filter */ @Test public void test1() { // Internal iteration: the iteration operation is completed by the Stream API employees.stream() .filter(e -> e.getAge() > 35) .forEach(System.out::println); // External iteration Iterator<Employee> it = employees.iterator(); while (it.hasNext()) { System.out.println(it.next()); } }
1.2 limit: interception
package cn.luis.stream.intermediate; import cn.luis.stream.Employee; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class LimitTest { List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11), new Employee(3, "Zhao Liu", 57, 3333.33), new Employee(4, "pseudo-ginseng", 35, 4444.44), new Employee(2, "Li Si", 49, 2222.22), new Employee(5, "pseudo-ginseng", 35, 4444.44) ); /** * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation" * 2.Filtering and slicing: limit */ @Test public void test2() { // limit; Short circuit, find two matching and terminate employees.stream() .filter(e -> { //System.out.println("unqualified or directly discarded!"+ e); return e.getAge() > 20; }) .limit(2) .forEach(System.out::println); } }
1.3 skip: skip
package cn.luis.stream.intermediate.shanxuanqiepian; import cn.luis.stream.common.Employee; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; public class SkipTest { List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11), new Employee(2, "Li Si", 49, 2222.22), new Employee(3, "Zhao Liu", 57, 3333.33), new Employee(4, "pseudo-ginseng", 35, 4444.44), new Employee(5, "pseudo-ginseng", 35, 4444.44) ); /** * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation" * 1.Filtering and slicing: skip */ @Test public void test3() { // limit; Skip the first two employees.stream() .filter(e -> e.getAge() > 18) .skip(2) .forEach(System.out::println); } }
1.4 distinct: weight removal
package cn.luis.stream.intermediate.shanxuanqiepian; import cn.luis.stream.common.Employee; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; public class DistinctTest { List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11), new Employee(2, "Li Si", 49, 2222.22), new Employee(3, "Zhao Liu", 57, 3333.33), new Employee(4, "pseudo-ginseng", 35, 4444.44), new Employee(5, "pseudo-ginseng", 35, 4444.44) ); /** * Filter and slice: distinct: filter to remove duplicate elements through hashCode() and equals() of the elements generated by the stream */ @Test public void test4() { // distinct; De duplication [employees to rewrite hashcode and equals] employees.stream() .filter(e -> { return e.getAge() > 25; }) .distinct() .forEach(System.out::println); } }
2. Mapping
The Function interface is passed into the map, and a parameter is passed in to return a value
method | describe |
---|---|
map | Receive lambda, convert elements into other forms or extract information, and receive a function as a parameter. The function will be applied to each element and mapped into a new element. |
flatMap | Receive a function as a parameter, replace each value in the stream with another stream, and then connect all streams into one stream |
example:
package cn.luis.stream.intermediate.yingshe; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class MapTest { List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd"); /** * map */ @Test public void test1() { list.stream() .map(s -> s.toUpperCase()) .forEach(System.out::println); System.out.println("--------------------------"); // This type of dolls can be replaced by flatMap (see test2) Stream<Stream<Character>> stream = list.stream().map(MapTest::filterCharacter); stream.forEach(sm -> { sm.forEach(System.out::println); }); } /** * flatMap: Flattened map */ @Test public void test2() { // Flattening map: originally, the stream was put into the map stream, but now the elements in the stream are directly put into the flatmap stream // Put {a,a,a},{b,b,b} Converted to {a, a, a, B, B, C, C, C} Stream<Character> characterStream = list.stream() .flatMap(MapTest::filterCharacter); characterStream.forEach(System.out::println); } /** * Split string * @param str * @return */ public static Stream<Character> filterCharacter(String str) { List<Character> list = new ArrayList<>(); for (Character ch : str.toCharArray()) { list.add(ch); } return list.stream(); } }
3. Sorting
method | describe |
---|---|
sorted() | Natural sorting (Comparable) |
sorted(Comparator com) | Custom sort (Comparator) |
example:
package cn.luis.stream.intermediate.sort; import cn.luis.stream.common.Employee; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class SortedTest { List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11), new Employee(2, "Li Si", 49, 2222.22), new Employee(3, "Zhao Liu", 57, 3333.33), new Employee(4, "pseudo-ginseng", 35, 4444.44), new Employee(5, "pseudo-ginseng", 35, 4444.44) ); /** * 3. sort * sorted() -- Natural sorting (Comparable) * sorted(Comparator) -- Custom sort (Comparator) */ @Test public void test1() { // Natural sorting ba Stream<Employee> sorted = employees.stream().sorted(); // Sort by age, same age, sort by name employees.stream() .sorted((e1, e2) -> { if (e1.getAge() == e2.getAge()) { return e1.getName().compareTo(e2.getName()); } else { Integer x = e1.getAge(); return x.compareTo(e2.getAge()); } }).forEach(System.out::println); } }
Terminate operation
1. Find and match
method | describe |
---|---|
allMatch | Check that all elements match |
anyMatch | Check to see if at least one element matches |
noneMatch | Check if not all elements match |
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 |
example:
- Find objects
List<Employee> employees = Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11, Status.BUSY), new Employee(2, "Li Si", 49, 2222.22, Status.FREE), new Employee(3, "Zhao Liu", 57, 3333.33, Status.BUSY), new Employee(4, "pseudo-ginseng", 35, 4444.44, Status.VOCATION), new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE), new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE), new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE) );
1.1 match: Match
@Test public void matchTest() { // Check that all elements match boolean b = employees.stream() .allMatch(e -> Employee.Status.BUSY.equals(e.getStatus())); System.out.println(b); // Check to see if at least one element matches boolean b2 = employees.stream() .anyMatch(e -> Employee.Status.BUSY.equals(e.getStatus())); System.out.println(b2); // Check if not all elements match boolean b3 = employees.stream() .noneMatch(e -> Employee.Status.BUSY.equals(e.getStatus())); System.out.println(b3); }
1.2 find: find
@Test public void findTest() { // Returns the first element Optional<Employee> first = employees.stream() .sorted(Comparator.comparingDouble(Employee::getSalary)) .findFirst(); System.out.println(first.get()); // Returns any element in the current stream Optional<Employee> any = employees.stream() .filter(e -> Employee.Status.FREE.equals(e.getStatus())) .findAny(); System.out.println(any.get()); // [parallel] returns any element in the current stream Optional<Employee> any2 = employees.parallelStream() .filter(e -> Employee.Status.FREE.equals(e.getStatus())) .findAny(); System.out.println(any2.get()); }
1.3 maximum value
@Test public void numTest() { // Returns the total number of elements in the stream long count = employees.stream() .count(); System.out.println(count); // Returns the maximum value in the stream Optional<Employee> max = employees.stream() .max(Comparator.comparingDouble(Employee::getAge)); System.out.println(max.get()); // Returns the minimum value in the stream Optional<Double> min = employees.stream() .map(Employee::getSalary) .min(Double::compare); System.out.println(min.get()); }
2. Statute
method | describe |
---|---|
reduce | You can combine the elements in the flow repeatedly to get a value |
- Prepare data
public class EmpData { public static List<Employee> findAllEmployee() { return Arrays.asList( new Employee(1, "Zhang San", 18, 1111.11, Employee.Status.BUSY), new Employee(2, "Li Si", 49, 2222.22, Employee.Status.FREE), new Employee(3, "Zhao Liu", 57, 3333.33, Employee.Status.BUSY), new Employee(4, "pseudo-ginseng", 35, 4444.44, Employee.Status.VOCATION), new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE), new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE), new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE) ); } }
- example:
/** * Statute */ public class ReduceTest { List<Employee> employees = EmpData.findAllEmployee(); /** * reduce(Starting value, binary operation): Protocol */ @Test public void test3() { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); Integer a = list.stream() .reduce(0, (x, y) -> x + y); System.out.println(a); Integer b = list.stream() .reduce(0, Integer::sum); System.out.println(b); // Optimized writing method (map reduce mode) Optional<Integer> c = list.stream() .reduce(Integer::sum); System.out.println(c.get()); // Optimized writing method (map reduce mode) + orElse Integer d = list.stream() .reduce(Integer::sum).orElse(0); System.out.println(d); } }
3. Collection
Including set, calculation, grouping and partition
method | describe |
---|---|
collect | Convert the Stream into other forms and receive the implementation of a Collectot interface, which is used to summarize the elements in the Stream |
3.1 assembly
@Test public void test4() { List<String> nameList = employees.stream() .map(Employee::getName) .collect(Collectors.toList()); nameList.forEach(System.out::println); System.out.println("-----------Filter duplicate data--------------"); Set<String> nameSet = employees.stream() .map(Employee::getName) .collect(Collectors.toSet()); nameSet.forEach(System.out::println); System.out.println("-----------Drop to other collection types--------------"); HashSet<String> nameHashSet = employees.stream() .map(Employee::getName) .collect(Collectors.toCollection(HashSet::new)); nameHashSet.forEach(System.out::println); }
3.2 calculation
@Test public void test5() { // total Long collect = employees.stream() .collect(Collectors.counting()); System.out.println(collect); // average value Double avg = employees.stream() .collect(Collectors.averagingDouble(Employee::getSalary)); System.out.println(avg); // Maximum Optional<Double> max = employees.stream() .map(Employee::getSalary) .collect(Collectors.maxBy(Double::compare)); System.out.println(max.get()); // minimum value Optional<Double> min = employees.stream() .map(Employee::getSalary) .collect(Collectors.minBy(Double::compare)); System.out.println(min.get()); // the sum Double sum = employees.stream() .collect(Collectors.summingDouble(Employee::getSalary)); System.out.println(sum); // Double: powerful computing DoubleSummaryStatistics salary = employees.stream() .collect(Collectors.summarizingDouble(Employee::getSalary)); System.out.println(salary.getAverage()); System.out.println(salary.getMax()); System.out.println(salary.getCount()); }
3.3 grouping and zoning
- partition
List<Employee> employees = EmpData.findAllEmployee(); /** * collect Grouping of */ @Test public void groupTest1() { // grouping Map<Employee.Status, List<Employee>> statusListMap = employees.stream() .collect(Collectors.groupingBy(Employee::getStatus)); statusListMap.keySet().forEach(System.out::println); statusListMap.entrySet().forEach(System.out::println); System.out.println(statusListMap); } /** * collect Grouping of */ @Test public void groupTest2() { // Multilevel grouping Map<String, List<Employee>> emMap = employees.stream() .collect(Collectors.groupingBy((employee) -> { if (employee.getAge() <= 35) { return "youth"; } else if (employee.getAge() > 20) { return "old age"; } else { return "juvenile"; } })); // View grouping (first method) emMap.keySet().forEach(key -> { System.out.println("======" + key + "======"); emMap.get(key).forEach(System.out::println); }); // View grouping (second way) emMap.forEach((k, v) -> { System.out.println("======" + k + "======"); v.forEach(map -> { System.out.println(map); }); }); }
- result:
======youth====== Employee(id=1, name=Zhang San, age=18, salary=1111.11, status=BUSY) Employee(id=4, name=pseudo-ginseng, age=35, salary=4444.44, status=VOCATION) ======old age====== Employee(id=2, name=Li Si, age=49, salary=2222.22, status=FREE) Employee(id=3, name=Zhao Liu, age=57, salary=3333.33, status=BUSY) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)
- grouping
/** * collect Partition of */ @Test public void area1() { // Zoning: a zone is divided into those that meet the conditions and those that do not meet the conditions Map<Boolean, List<Employee>> emMap = employees.stream() .collect(Collectors.partitioningBy(e -> e.getSalary() > 2000.0)); // View grouping (second way) emMap.forEach((k, v) -> { System.out.println("======" + k + "======"); v.forEach(map -> { System.out.println(map); }); }); }
- result
======false====== Employee(id=1, name=Zhang San, age=18, salary=1111.11, status=BUSY) ======true====== Employee(id=2, name=Li Si, age=49, salary=2222.22, status=FREE) Employee(id=3, name=Zhao Liu, age=57, salary=3333.33, status=BUSY) Employee(id=4, name=pseudo-ginseng, age=35, salary=4444.44, status=VOCATION) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE) Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)