​(十)JAVA基础及提高篇JDK8之Stream流详细说明

一、了解 Stream

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*)。Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

二、什么是 Stream

流(Stream) 到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!"

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

三、Stream 的操作三个步骤

 创建 Stream一个数据源(如: 集合、数组), 获取一个流

 中间操作一个中间操作链,对数据源的数据进行处理

 终止操作(终端操作)一个终止操作,执行中间操作链,并产生结果

1.创建 Stream 

Java8 中的 Collection 接口被扩展,提供了两个获取流的方法: 

 default Stream<E> stream() : 返回一个顺序流
 default Stream<E> parallelStream() : 返回一个并行流
 

由数组创建流
Java8 中的 Arrays 的静态方法 stream() 可
以获取数组流:
 static <T> Stream<T> stream(T[] array): 返回一个流
重载形式,能够处理对应基本类型的数组:
 public static IntStream stream(int[] array)
 public static LongStream stream(long[] array)
 public static DoubleStream stream(double[] array)

代码demo说明

        IntStream stream = Arrays.stream(new int[]{1, 2, 3});
        LongStream stream1 = Arrays.stream(new long[2]);
        DoubleStream stream2 = Arrays.stream(new double[1]);


由值创建流
可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values) : 返回一个流

demo

Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 9, 8, 7, 3);


由函数创建流:创建无限流
可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。

 迭代
public static<T> Stream<T> iterate(final T seed, final
UnaryOperator<T> f)
 生成
public static<T> Stream<T> generate(Supplier<T> s) :
 

2.Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值” 。

代码demo说明 

Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 9, 8, 7, 3);
List<Integer> list = integerStream.filter(a -> a > 3).collect(Collectors.toList());
System.out.println(list);
//打印结果
//[4, 5, 6, 9, 8, 7]
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 9, 8, 7, 3);
        List<Integer> list = integerStream.limit(3).collect(Collectors.toList());
        System.out.println(list);

 代码demo说明 

Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 9, 8, 7, 3);
List<Integer> list = integerStream.map(a->a==1?2:a).collect(Collectors.toList());
System.out.println(list);
flatmap 将多维嵌套列表转换为单维列表
String[] strs = {"java8", "is", "easy", "to", "use"};
Stream<String> stream1 = Arrays.stream(strs);
Stream<String[]> stream = Arrays.stream(strs).map(str -> str.split(""));
Stream<String> stream2 = stream.flatMap(Arrays::stream);

 demo

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7});
List<Integer> collect = stream.sorted((a, b) -> a > b ? 1 : -1).collect(Collectors.toList());
System.out.println(collect); //打印如下: [1, 2, 2, 3, 4, 6, 7, 7, 9]

3.Stream 的终止操作 

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如: List、 Integer,甚至是 void 。 

 

demo 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7});
Optional<Integer> any = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7}).findAny();
Optional<Integer> first = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7}).findFirst();
boolean b = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7}).anyMatch(a -> a == 5);
System.out.println(any.get());//1
System.out.println(first.get());//1
System.out.println(b);//false

 

 

demo 

 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7});
OptionalInt max = stream.mapToInt(a -> a).max();
System.out.println(max.getAsInt());

demo 

 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7});
Optional<Integer> reduce = stream.reduce((a, b) -> a + b);
System.out.println(reduce.get());//累加 41

 

Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、 Set、 Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下表: 
 

demo 

 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 30, 6, 7});
Integer collect = stream.collect(Collectors.summingInt(a -> a));
System.out.println(collect);//求和 68

demo 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 30, 6, 7});
Double collect = stream.collect(Collectors.averagingInt(a -> a));
System.out.println(collect);//求平均值 7.555555555555555

 

demo 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 30, 6, 7});
Optional<Integer> collect = stream.collect(Collectors.maxBy((a, b) -> a - b));
System.out.println(collect.get());//求最大值 30

 

demo 

Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 9, 7, 4, 2, 3, 6, 7});
Long collect = stream.collect(Collectors.counting());
System.out.println(collect);//求个数 9

 

四、并行流与串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。 Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。

了解 Fork/Join 框架 

Fork/Join 框架: 就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总 

Fork/Join 框架与传统线程池的区别

采用 “工作窃取”模式(work-stealing):
当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。

相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果
某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值