在JDK 8 之后增加了java.util.stream 包,这个Stream 不同与IO的流。官方的描述”Classes to support functional-style operations on streams of elements, such as map-reduce transformations on collections. “ 支持元素流功能性操作的类,例如集合上的map-reduce转换。
Stream API 引入的目的是支持函数式的操作,比如在集合上面很多的业务都是相关的,例如排序、求最大值等,既然都有这样的操作,那么就可以抽取出来,进行连续的操作。这样的连续操作,就类似于流水的进行,也就是流式操作。
分类 流(Stream)的操作主要分成两类: 1.中间的(intermediate) : 中间的操作保持流的打开状态,并允许后续的操作。一个流可以后面跟随零个或多个 中间的(intermediate) 操作。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
如:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
2.末端的(Terminal) : 末端的(Terminal)操作必须是对流的最终操作,一个流只能有一个 terminal 操作,当这个操作执行后。
如:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
还有一种操作被称为 short-circuiting。用以指: 对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。 对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
如:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
操作流程 1.获取一个流 2.执行一个或者多个中间的操作 3.执行一个末端的操作
流的获取 1.对于数组
2.对于集合Collection
3.对于Map Map 本身没有流,但具有类似的操作,如:
1 2 3 map.putIfAbsent map.computeIfPresent map.merge
对于基本数据类中,目前具有三种对应的包装类型 Stream :IntStream、LongStream、DoubleStream
当然我们也可以用 Stream、Stream >、Stream,但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。
流的并行计算 只需要讲×.stream() 换成 *.parallelStream()
流的使用实例 以下特性是JDK 1.8 才具有的,所以需要设置JRE是在1.8的情况下:
ForEach 与 peek forEach 是 terminal 操作,因此它执行后,Stream 的元素就被“消费”掉了,你无法对一个 Stream 进行两次 terminal 运算。相反,具有相似功能的 intermediate 操作 peek 可以达到上述目的。 Stream peek(Consumer<? super T> action) 返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。 这是一个中间操作。对于并行流管线,可以在上游操作的任何时间和任何线程中调用该元素可用的动作。 如果操作修改共享状态,则负责提供所需的同步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.devnp.java8.stream;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;public class ForEachDemo { public static void main (String[] args) { List<String> strings = Arrays.asList("abc" , "cbc" , "bbc" , "cbc" , "uas" ,"cctv" , "cnc" ); strings.stream().forEach(System.out::println); System.out.println("----------------------------" ); strings.stream().forEach(p -> System.out.println(p)); System.out.println("----------------------------" ); strings.stream().peek(e -> System.out.println(e)).collect(Collectors.toList()); Stream.of("one" , "two" , "three" , "four" ) .filter(e -> e.length() > 3 ) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList()); } }
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 abc cbc bbc cbc uas cctv cnc ---------------------------- abc cbc bbc cbc uas cctv cnc ---------------------------- abc cbc bbc cbc uas cctv cnc Filtered value: three Mapped value: THREE Filtered value: four Mapped value: FOUR
Map Stream map(Function<? super T,? extends R> mapper) 返回由给定函数应用于此流的元素的结果组成的流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.devnp.java8.stream;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;public class MapDemo { public static void main (String[] args) { List<Integer> numbers = Arrays.asList(1 , 2 , 2 , 4 , 5 , 6 , 7 ); List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); squaresList.stream().forEach(p -> System.out.println(p)); } }
输出结果
Filter
Stream filter(Predicate<? super T> predicate) 返回由与此给定谓词匹配的此流的元素组成的流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.devnp.java8.stream;import java.util.stream.Stream;public class FilterDemo { public static void main (String[] args) { Stream<String> strings = Stream.of("one" , "two" , "three" , "four" ) ; strings.filter(p -> p.length() > 3 ).forEach(p -> System.out.println(p)); ; } }
输出结果:
limit
Stream limit(long maxSize) 返回由此流的元素组成的流,截断长度不能超过maxSize。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.devnp.java8.stream;import java.util.stream.Stream;public class LimitDemo { public static void main (String[] args) { Stream<String> strings = Stream.of("one" , "two" , "three" , "four" ) ; strings.limit(2 ).forEach(p -> System.out.println(p)); ; } }
输出结果:
sorted
Stream sorted() 返回由此流的元素组成的流,根据自然顺序排序。如果节点不能比较会抛出java.lang.ClassCastException Stream sorted(Comparator<? super T> comparator) 返回由该流的元素组成的流,根据提供的比较器进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.devnp.java8.stream;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class SortedDemo { public static void main (String[] args) { List<Integer> numbers = Arrays.asList(8 , 2 , 1 , 4 , 5 , 6 , 7 ); numbers.stream().sorted().forEach(p -> System.out.print(p + "," )); System.out.println(); List<Person> persons = new ArrayList <>(); Person person1 = new Person ("ebcs" , 20 ); Person person2 = new Person ("dfbcs" , 21 ); Person person3 = new Person ("hbcs" , 25 ); Person person4 = new Person ("cbcs" , 18 ); persons.add(person1); persons.add(person2); persons.add(person3); persons.add(person4); persons.stream().sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).forEach(p -> System.out.print(p.getName() + "," )); } } class Person { private String name ; private Integer age ; public Person () { super (); } public Person (String name, Integer age) { super (); this .name = name; this .age = age; } 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; } }
运行结果:
1 2 1,2,4,5,6,7,8, cbcs,dfbcs,ebcs,hbcs,
min/max/count Optional max(Comparator<? super T> comparator) 根据提供的比较器返回此流的最大元素。 这是减少的一个特例。 Optional min(Comparator<? super T> comparator) 根据提供的比较器返回该流的最小元素。 long count() 返回此流中的元素数。 IntStream mapToInt(ToIntFunction<? super T> mapper) 返回一个IntStream,其中包含将给定函数应用于此流的元素的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.devnp.java8.stream;import java.util.Arrays;import java.util.IntSummaryStatistics;import java.util.List;public class StatisticsDemo { public static void main (String[] args) { List<Integer> numbers = Arrays.asList(8 , 2 , 1 , 4 , 5 , 6 , 7 ); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Max : " + stats.getMax()); System.out.println("Min : " + stats.getMin()); System.out.println("Sum : " + stats.getSum()); System.out.println("Average : " + stats.getAverage()); System.out.println("Count : " + stats.getCount()); long count = numbers.stream().count(); System.out.println("Stream count : " + count); } }
运行结果:
1 2 3 4 5 6 Max : 8 Min : 1 Sum : 33 Average : 4.714285714285714 Count : 7 Stream count : 7
Match Stream 有三个 match 方法,从语义上说: boolean anyMatch(Predicate<? super T> predicate); allMatch:Stream 中全部元素符合传入的 predicate,返回 true
boolean allMatch(Predicate<? super T> predicate); anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
boolean noneMatch(Predicate<? super T> predicate); noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package com.devnp.java8.stream;import java.util.ArrayList;import java.util.List;public class MatchDemo { public static void main (String[] args) { List<Student> students = new ArrayList <>(); Student person1 = new Student ("ebcs" , 20 ); Student person2 = new Student ("dfbcs" , 21 ); Student person3 = new Student ("hbcs" , 25 ); Student person4 = new Student ("cbcs" , 18 ); students.add(person1); students.add(person2); students.add(person3); students.add(person4); boolean isAllAdult = students.stream().allMatch(p -> p.getAge() > 18 ); System.out.println("All are adult? " + isAllAdult); boolean isThereAnyChild = students.stream().anyMatch(p -> p.getAge() < 12 ); System.out.println("Any child? " + isThereAnyChild); boolean noChild = students.stream().noneMatch(p -> p.getAge() < 12 ); System.out.println("No child? " + noChild); } } class Student { private String name ; private Integer age ; public Student () { super (); } public Student (String name, Integer age) { super (); this .name = name; this .age = age; } 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; } }
运行结果:
1 2 3 All are adult? false Any child? false No child? true
代码下载 java-hibernate-core-demo.zip
Author:
Darren Du
License:
Copyright (c) 2019 MIT LICENSE