1.管道与流
管道:就是一系列的聚合操作
组件:
- 源:可以是集合,数组,生成器函数或I/O通道
- 零个或多个中间操作。诸如过滤器之类的中间操作产生新的流
- 终结操作。终端操作(例如forEach)会产生非流结果,例如原始值(如双精度值),集合,或者在forEach的情况下根本没有任何值
流:一系列元素
- 与集合不同,它不是存储元素的数据结构,取而代之的是,流通过管道携带来自源的值
- 筛选器操作返回一个新流,该流包括与筛选条件(此操作的参数)匹配的元素
2.如何获取Stream流
Collection接口
default Stream<E> stream();
Stream接口
//获取流
public static<T> Stream<T> of(T... values);
//将两个流拼接形成一个新的流
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);
3.Stream流中间聚合操作
Stream接口
Stream<T> filter(Predicate<? super T> predicate);//根据给定的条件过滤流中的元素
<R> Stream<R> map(Function<? super T, ? extends R> mapper);//将流中元素进行类型转换
Stream<T> distinct();//去重
Stream<T> sorted();//排序,如果存储元素没有实现Comparable或者相关集合没有提供 Comparator将抛出异常
Stream<T> limit(long maxSize);//根据给定的上限,获取流中的元素
Stream<T> skip(long n);//跳过给定数量的元素
IntStream mapToInt(ToIntFunction<? super T> mapper);//将流中元素全部转为整数
LongStream mapToLong(ToLongFunction<? super T> mapper);//将流中元素全部转为长整数
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);//将流中元素全部 转为双精度浮点数
4.Stream流终结操作
终结操作只能执行一次,返回的都不是Stream
void forEach(Consumer<? super T> action);//遍历操作流中元素
<A> A[] toArray(IntFunction<A[]> generator);//将流中元素按照给定的转换方式转换为数组
<R, A> R collect(Collector<? super T, A, R> collector);//将流中的元素按照给定的 方式搜集起来
Optional<T> min(Comparator<? super T> comparator);//根据给定的排序方式获取流中最 小元素
Optional<T> max(Comparator<? super T> comparator);//根据给定的排序方式获取流中最 大元素
Optional<T> findFirst(); //获取流中第一个元素 long count();//获取流中元素数量
boolean anyMatch(Predicate<? super T> predicate);//检测流中是否存在给定条件的元素
boolean allMatch(Predicate<? super T> predicate);//检测流中元素是否全部满足给定条件
boolean noneMatch(Predicate<? super T> predicate);//检测流中元素是否全部不满足给 定条件
5.Stream流聚合操作与迭代器的区别
[官网]聚合操作(如forEach)似乎像迭代器。但是,它们有几个基本差异:
- 它们使用内部迭代:聚合操作不包含诸如next的方法来指示它们处理集合的下一个元素。使用内部委托,你的应用程序确定要迭代的集合,而JDK确定如何迭代该集合。通过外部迭代,你的应用程序既可 以确定要迭代的集合,又可以确定迭代的方式。但是,外部迭代只能顺序地迭代集合的元素。内部迭代没有此限制。它可以更轻松地利用并行计算的优势,这涉及将问题分为子问题,同时解决这些问题,然后将解决方案的结果组合到子问题中。
- 它们处理流中的元素:聚合操作从流中而不是直接从集合中处理元素。因此,它们也称为流操作。
- 它们支持将行为作为参数:你可以将lambda表达式指定为大多数聚合操作的参数。这使你可以自定义特定聚合操作的行为。
面试题
使用Stream流将一个基本数据类型的数组转换为包装类型的数组,再将包装类型的数组转换基本类型数组
int[] intArr = {1,2,3,4,5};
// Integer[] intArr2 = Arrays.stream(intArr).mapToObj(value ->value).toArray(value -> new Integer[value]);
Integer[] intArr2 = Arrays.stream(intArr).boxed().toArray(Integer[]::new);
Integer[] intArr3 = {1,2,3,4,5};
int[] intArr4 = Arrays.stream(intArr3).mapToInt(Integer::intValue).toArray();