java8 Stream

java8 Stream 操作

内循环和外循环

里和外是相对于集合本身。集合自己的遍历是内循环,通过iterator 进行的遍历为外循环
jdk8以前的java 集合是通过实现了iterator 接口,集合通过iterator.next 来进行遍历。
常见的写法是for(int i : List)
对于内循环,只需要告诉这个stream 需要循环做什么就可以了。


Stream

jdk8 中新添加的一组包,java.lang.stream
每个流代表一个值序列,流提供一系列常用的聚集操作,使得我们可以便捷的在它上面进行各种运算。集合类库也提供了便捷的方式使我们可以以操作流的方式使用集合、数组以及其它数据结构。stream具有以下特点:
1. 函数式编程:通过操作返回一个新的结果,但是不会对源数据改变
2. 无存储:stream 的操作不会存储值,只是进行计算
3. 惰性求值:多数的stream 操作都可以使用惰性操作,好处就是不会多次遍历一个集合。
4. 无需上界:集合是有限的,但stream 不是,客户端可以不断的读取结果,直到出现合适的结果为止

惰性求值:stream 中的操作可以分为两种,一种是 返回stream ,一种返回非stream
对于返回stream的操作会被惰性操作。对于非stream 的操作会马上进行计算并返回结果,急性求值。惰性求值是指,对一个序列进行操作会在遇到一个急性求值时,才会对所有的操作放到一起进行执行。惰性求值会减少大量的多次遍历


多线程

从一个序列获取stream 有两个方法

//返回单线程的stream 
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}
//多线程的stream
default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
}

一个单线程的操作转成支持多线程的操作时只需要改变获取stream的方法,但是这里有几个点需要注意:

  1. 不对源数据进行操作。
  2. 不对表达式外部的变量进行共享性的操作

元素的操作顺序

stream 中元素的操作顺序是根据源数据的顺序来的。
比如Arraylist 是有序的集合,那么stream 的操作是按照ArrayList 的顺序进行操作。如果是HashSet的操作,那操作也是无序的


收集操作

集合操作后,把操作的结果通过collect() 保存到一个集合中。 Collectors 类包含了大量常用收集器的工厂方法, toList() 和 toSet() 就是其中最常见的两个,除了它们还有很多收集器,用来对数据进行对复杂的转换。

Collector的类型由其输入类型和输出类型决定。以 toList() 收集器为例,它的输入类型为T ,输出类型为 List , toMap 是另外一个较为复杂的 Collector ,它有若干个版本。最简单的版本接收一对函数作为输入,其中一个函数用来生成键(key),另一个函数用来生成值(value)。 toMap 的输入类型是 T ,输出类型是 Map ,其中 K 和 V 分别是前面两个函数所生成的键类型和值类型。(复杂版本的 toMap 收集器则允许你指定目标 Map 的类型或解决键冲突)。举例来说,下面的代码以目录数字为键值创建一个倒排索引

groupingBy 是一个与 toMap 相类似的收集器,比如说我们想要把我们最喜欢的音乐按歌手列出来,这时我们就需要这样的 Collector :它以 Track 作为输入,以 Map> 作为输出。 groupingBy 收集器就可以胜任这个工作,它接收分类函数(classification function),然后根据这个函数生成 Map ,该 Map 的键是分类函数的返回结果,值是该分类下的元素列表。

常见方法

filter:对序列中的每个元素进行筛选。

Stream<T> filter(Predicate<? super T> predicate);

map:对于集合中的每个元素执行Function 函数

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

mapToDouble,mapToInt,mapToLong:返回不同类型的stream

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);

flatMap:把生成的stream 合并成一个stream

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

reduce:对于集合中的每两个相邻的元素执行 BinaryOperator 操作

Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator); //提供初始值的操作
<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);