jdk1.8——Stream

Stream是jdk1.8提供的新的流式编程,它不是集合也不保存任何内容,可以像build对象一样,一直点点点最后跟一个终结语句;

研究Stream之前需要先了解:

  • 新的接口定义:jdk1.8——接口新的默认方法和静态方法_FlyLikeButterfly的博客-CSDN博客
  • 函数式接口:jdk1.8——函数式接口_FlyLikeButterfly的博客-CSDN博客
  • Lambda表达式:jdk1.8——Lambda表达式_FlyLikeButterfly的博客-CSDN博客
  • 方法引用:jdk1.8——方法引用_FlyLikeButterfly的博客-CSDN博客

Stream的特性:

不是数据结构,不保存数据;
不修改原始数据,会将产生的新数据保存到新对象中;
延迟操作,中间的操作只会记录,直到它弄清楚了最后需要多少数据才会开始执行;
拥有并行能力(基于 Fork/Join 框架);
数据源可以是无限的;
消费性,用完了不能再拿来用,只能重新生成新的 stream

注:对于基本数据类型,另外有三个包装Stream类型:IntStream、LongStream、DoubleStream,这三个类型跟Stream类稍微有些差别,例如不需要泛型、特有的方法等;

生成Stream的方式:

  • 用Collection的stream()和parallelStream()

 

  • Arrays的stream()

  • Stream类的静态方法of()、iterate()、generate()

jdk1.8——Stream_第1张图片

  • BufferedReader.lines()

jdk1.8——Stream_第2张图片 

  • Pattern的splitAsStream()

 

  • IntStream.range()

  • Files.walk()

 

  • Random的ints()

  • BitSet.stream()

jdk1.8——Stream_第3张图片

  • JarFile.stream()

  • 通过Stream.builder()的builde()

Stream的操作类型:

  • Intermediate(中间操作)​​​​​​

一个流后面可以跟0个或多个中间操作,主要是对数据做一些过滤映射操作,然后返回流交给下一个操作,中间操作是惰性的,只会记录操作过程,不会真正开始遍历数据;中间操作分无状态和有状态两种操作,无状态的每个元素可单独处理,跟其他元素无关联(filter,map),有状态的元素需要知道其他元素distinct,sorted);在并行时,某些有状态的操作可能回遍历数据多次或者缓冲大量数据(sorted不适合用并行);

  • Terminal(终止操作)

一个流只能有一个终止操作,必定是最后一个操作,执行完后流就被用完了不能再被使用,终止操作执行的时候才会真正开始遍历数据,返回数据或者执行一段代码;

  • 还有一种short-circuiting(短路操作,是处理无限流时的必要不充分条件)

中间操作的短路,会产生有限的流;终止操作的短路,会在有限时间内终止;

Stream类的方法详解:

  • 静态方法

builder(), concat(Stream, Stream), empty(), generate(Supplier), iterate(T, UnaryOperator), of(T), of(T...)

  • allMatch(Predicate)

(短路终止)元素都匹配返回true,否则false;(中间遇到不匹配立即返回flase)

jdk1.8——Stream_第4张图片

  • anyMatch(Predicate)

(短路终止)存在匹配返回true,否则flase;(中间存在一个匹配立即返回true)

  • collect(Supplier, BiConsumer, BiConsumer)
  • collect(Collector)

(终止)将流转换成集合和聚合元素;

jdk1.8——Stream_第5张图片

  • count()

(终止)返回流的元素数量;

  • distinct()

(状态中间)去重,对于有序流保留第一个,无序流是随机的;

  • filter(Predicate)

(中间)过滤元素;

 

  • findAny()

(短路终止)返回流中任意一个元素;

  • findFirst()

(短路终止)返回流中第一个元素;

 

  • forEach(Consumer)
  • forEachOrdered(Consumer)

(终止)遍历,有序流ordered保证顺序(并行);

jdk1.8——Stream_第6张图片 

  • flatMap(Function>)
  • flatMapToDouble(Function)
  • flatMapToInt(Function)
  • flatMapToLong(Function)

(中间)扁平映射,一个映射多个;

jdk1.8——Stream_第7张图片

jdk1.8——Stream_第8张图片

  • isParallel()

是否是并行流(继承方法);

  • iterator()

返回流的迭代器(继承方法);

  • limit(long)

(短路状态中间)截断流的最大长度;

  • map(Function)
  • mapToDouble(ToDoubleFunction)
  • mapToInt(ToIntFunction)
  • mapToLong(ToLongFunction)

(中间)映射,一对一;

 

  • max(Comparator)

(终止)根据比较规则返回最大值

  • min(Comparator)

(终止)根据比较规则返回最小值(compare返回<=0则返回第一个)

  • noneMatch(Predicate)

(短路终止)没有相匹配的返回true,一旦匹配立即返回false;

 

  • close()

关闭流(继承方法);

  • onClose(Runnable)

(中间)调用close()的时候触发,所有的onClose定义的runnable都会按添加顺序执行(即使有的runnable抛出异常),run中抛出的第一个异常将在close()方法中抛出,其他异常会作为抑制异常被添加到该抛出异常中(继承方法);

jdk1.8——Stream_第9张图片jdk1.8——Stream_第10张图片

  • parallel()

(中间)将流变成并行流(继承方法);

  • sequential()

(中间)将流变成串行流(继承方法);

  • peek(Consumer)

(中间)元素在结果流中被消耗时,额外对每个元素执行该操作;

jdk1.8——Stream_第11张图片jdk1.8——Stream_第12张图片

  • reduce(BinaryOperator)
  • reduce(T, BinaryOperator)
  • reduce(U, BiFunction, BinaryOperator)

(终止)对元素进行累加操作;

jdk1.8——Stream_第13张图片

jdk1.8——Stream_第14张图片

jdk1.8——Stream_第15张图片

  • skip(long)

(状态中间)丢弃前n个元素,可能返回空流;

  • sorted()

(状态中间)按自然元素排序;

  • sorted(Comparator)

(状态中间)根据比较器排序;

jdk1.8——Stream_第16张图片

jdk1.8——Stream_第17张图片

jdk1.8——Stream_第18张图片

jdk1.8——Stream_第19张图片

jdk1.8——Stream_第20张图片

注:reversed()反向排序是对当前整个Comparator定义的排序取反;

  • spliterator()

(终止)返回流元素的拆分器(继承方法);

  • toArray()
  • toArray(IntFunction)

(终止)返回A[]元素数组(IntFunction的参数为元素个数);

jdk1.8——Stream_第21张图片 

  • unordered()

(中间)返回一个无序的流(继承方法);

IntStream的其他特有方法:

  • range(int, int)

返回一个整数序列,不包括最后一个(静态方法);

  • rangeClosed(int, int)

返回一个整数序列,包括最后一个(静态方法);

 

  • asDoubleStream()

(中间)转换成DoubleStream;

  • asLongStream()

(中间)转换成LongStream;

  • average()

(终止)返回算数平均值的OptionalDouble对象;

  • boxed()

(中间)每个元素装箱成Integer对象,返回Stream

 

  • sum()

(终止)求和;

  • summaryStatistics()

(终止)返回一个IntSummaryStatistics对象,该对象包括流元素的概要数据;

jdk1.8——Stream_第22张图片jdk1.8——Stream_第23张图片

注:

  • IntStream只有一个collect(Supplier supplier, ObjIntConsumer accumulator, BiConsumer combiner)方法,需要boxed转成Stream在用其他的collect;
  • DoubleStream没有IntStream里的range、rangeClosed、asDoubleStream、asLongStream方法,其他除了类型基本一致;
  • LongStream没有IntStream里的asLongStream方法,其他除了类型基本一致;

注意事项:

jdk1.8——Stream_第24张图片

一个小Demo:

jdk1.8——Stream_第25张图片 jdk1.8——Stream_第26张图片

从Stream.of也能看得出区别:

jdk1.8——Stream_第27张图片

  1. 基本数据类型不是对象,基本数据类型的包装类型是对象,基本数据类型是在栈上分配的,包装类型是new出来的,在堆上分配;
  2. 关于数组,栈上分配的一个指向堆的指针,数组是一个对象,基本数据类型的数组就只是一个数组对象(数组内的元素直接是值),而包装类型的数组里的元素也是指针(指向包装类型的对象);

你可能感兴趣的:(JDK特性,Stream,jdk1.8)