Stream流
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
特点:
1 . 不是数据结构,不会保存数据。
2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(peek方法可以修改流中的元素)
3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。
Stream的操作符大体上分为两种:中间操作符和终止操作符。
Stream分类 | ||
中间操作 (intermediate operation) |
有状态 (stateful) |
distinct()、sorted()、limit(long maxSize)、skip(long n) |
无状态 (stateless) |
filter()、map()、mapToInt()、mapToLong()、mapToDouble()、 |
|
结束操作 (terminal operation) |
短路 (short-circuiting) |
anyMatch()、allMatch()、noneMatch()、findFirst()、findAny() |
非短路 (non short-circuiting) |
forEach()、forEachOrdered()、toArray()、reduce()、
|
具体用法
public class Stream_example { public static void main(String[] args) { List<Integer> numList = Arrays.asList(-2,1,2,4,3,3,5); List<Integer> twoList = Arrays.asList(7,8,9,11); /***************Intermediate中间操作*****************/ //sorted排序:默认升序,降序,自定义升降序 numList.stream().sorted().forEach(System.out::println); numList.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println); numList.stream().sorted(Comparator.comparing(Integer::intValue).reversed()).forEach(System.out::println); numList.stream().sorted((o1, o2) -> { if (o1.getName().equals(o2.getName())) { return o1.getAge() - o2.getAge(); } else { return o1.getName().compareTo(o2.getName()); } }); //filter:按条件过滤元素 numList.stream().filter(e -> e > 2).forEach(System.out::println); numList.stream().filter(Objects::nonNull).forEach(System.out::println); //distinct:去重 numList.stream().distinct().forEach(System.out::println); //skip:跳过前n个元素 numList.stream().skip(2).forEach(System.out::println); //limit:截取前n个元素 numList.stream().limit(14).forEach(System.out::println); //map、mapToInt、mapToLong、mapToDouble、mapToObj:每个元素遍历执行 numList.stream().mapToDouble(e -> e * 2).forEach(System.out::println); numList.stream().map(e -> new Function<Integer, Long>() { @Override public Long apply(Integer i) { return i * 3L; } }).forEach(System.out::println); //flatMap:将多个流合并压缩成一个流 Stream.of(numList, twoList).flatMap(e -> e.stream()).forEach(System.out::println); Stream.of(numList, twoList).flatMap(Collection::stream).forEach(System.out::println); //concat: 流拼接 Stream.concat(numList.stream(), twoList.stream()); //peek:可查看流中的元素,用于调试,如同于map,peek接收的是Consumer表达式,没有返回值 numList.stream().filter(e -> e > 2).peek(e -> System.out.println("Filtered value: " + e)).forEach(System.out::println); numList.stream().peek(e -> e.setAge(100)).forEach(System.out::println); //parallelStream:并行流,无序,线程不安全;基于fork/join框架 numList.parallelStream().forEach(System.out::println); //sequential:将并行流转成串行流 numList.parallelStream().filter(e -> e > 2).sequential().forEach(System.out::println); //parallel:将串行流转成并行流 numList.stream().filter(e -> e > 2).parallel().forEach(System.out::println); /*************terminal operation.终端操作*****************/ //forEach:遍历每个元素,forEachOrdered常用于并行流 numList.stream().forEach(System.out::println); numList.stream().forEachOrdered(System.out::println); //toArray:返回包含此流元素的数组 Object[] array = numList.stream().toArray(); Integer[] integers = numList.stream().toArray(Integer[]::new); //collect:返回各种类型 String s = numList.stream().map(x -> x + "").collect(Collectors.joining("|")); Long collect = numList.stream().collect(Collectors.counting()); List<Integer> list = numList.stream().collect(Collectors.toList()); ArrayList<Integer> arrayList = numList.stream().collect(Collectors.toCollection(ArrayList::new)); LinkedList<Object> linkedList = numList.stream().collect(LinkedList::new, LinkedList::add, LinkedList::addAll); String sb = numList.stream().collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString(); HashMap<Object, Object> hashMap = numList.stream().collect(HashMap::new, (x, y) -> { x.put(y, y); }, HashMap::putAll); list.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get();//最大值 list.stream().collect(Collectors.summingInt(Student::getAge));//总和 list.stream().collect(Collectors.averagingDouble(Student::getAge));//平均值 Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors.groupingBy(Student::getAge));//分组 Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getType, Collectors.groupingBy(Student::getAge)));//多重分组 Map<Boolean, List<Student>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));//分区,一部分大于10,一部分小于等于10 //min:返回当前流中最小元素,max同理 Integer integer = numList.stream().min(Integer::compareTo).get(); Integer integer1 = numList.stream().min(Integer::compare).get(); int min = numList.stream().mapToInt(i -> i).min().getAsInt(); //count:统计条数 long count = numList.stream().count(); long sum = numList.stream().mapToLong(e -> 1L).sum(); //allMatch:判断的条件里,所有元素匹配,才返回true //anyMatch:判断的条件里,任意一个元素匹配,才返回true //noneMatch:判断的条件里,所有元素都不匹配,才返回true boolean b = numList.stream().allMatch(x -> x>2); boolean b1 = numList.stream().anyMatch(x -> x > 2); boolean b2 = numList.stream().noneMatch(x -> x == 0); //findFirst:返回列表中的第一个元素 //findAny:一般返回第一个结果,并行情况下不能确保是第一个 //orElse:返回对象,如果没有,则返回x Integer inte = numList.parallelStream().findFirst().get(); Integer inte1 = numList.stream().findAny().get(); Integer inte2 = numList.stream().filter(e -> e > 2).findAny().orElse(null); //关联累加 Integer reduce = numList.stream().reduce(Integer::sum).get(); Integer reduce1 = numList.stream().reduce((a, c) -> a + c).get(); Integer reduce2 = numList.stream().reduce(100, Integer::sum); Integer reduce3 = numList.stream().reduce(100, (a, c) -> a + c); Long reduce4 = numList.stream().reduce(100L, (a, c) -> a + c, (a, c) -> 0L); /***************short-circuiting terminal operation.短路操作*****************/ //summaryStatistics:返回各种汇总数据 IntSummaryStatistics summaryStatistics = numList.stream().mapToInt(e -> e).summaryStatistics(); IntSummaryStatistics intSummaryStatistics = IntStream.of(4, 5, 6, 7).summaryStatistics(); System.out.println(summaryStatistics.getMax()); System.out.println(summaryStatistics.getMin()); System.out.println(summaryStatistics.getSum()); System.out.println(summaryStatistics.getAverage()); System.out.println(summaryStatistics.getCount()); /*************** 流重用 *****************/ System.out.println("----------------------------------"); Iterable<Integer> iterable = () -> IntStream.range(1, 10).map(i -> ++i).iterator(); for (Integer item : iterable) { System.out.println(item); } System.out.println("-----------------无限流-----------------"); IntStream naturalNumbers = IntStream.iterate(1, x -> x + 1); naturalNumbers.limit(5).forEach(System.out::println); } }