Java 集合的流式操作

Java 8 引入,位于java.util.stream包中,与 java.io 包里的输入输出流 InputStream 和 OutputStream 是不同的概念。

Stream API 借助 Lambda 表达式,可以提高编程效率和程序可读性。

Stream的特性:

  • 元素序列:流提供了一个特定类型元素的集合,不存储元素,只获取和计算元素
  • 源:Collection/Arrays( Arrays.stream(Object[]))/ I/O channel等
  • 聚合操作:filter, map, limit, reduce, find, match等
  • 管道:中间操作返回流本身,多个操作可以组成流水线
  • 自动迭代:内部对源进行自动的迭代

流的操作类型分为两种,组成一个流管道

  • Intermediate:流可以后面跟有零个或多个中间操作
  • Terminal:流只能有一个终结操作,位于最后,例如 Stream.forEach / IntStream.sum等,产生一个最终结果,或者一个副作用(side effect)

提供串行( Collection.stream())和并行(Collection.stream())两种模式进行操作

Intermediate操作都是 lazy 的,多个操作只会在 Terminal 操作的时候融合起来执行,一次循环完成

操作一个无限大的 Stream,而又希望在有限时间内完成操作,需要进行短路(short-circuiting)操作,比如limit()

Stream生成

  • 集合: Collection接口中的stream() / parallelStream()方法
  • 数组: Arrays.stream(Object[]);
  • 静态方法 :Stream.of(Object[]), IntStream.range(int, int),Stream.iterate(Object, UnaryOperator)
  • 文件:BufferedReader.lines()
  • 随机数: Random.ints()
  • 其他: BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence), JarFile.stream()

常用的方法StreamSupport.stream(Spliterator spliterator, boolean parallel),其中Spliterator接口的含义如下:

  • 遍历:遍历单个元素tryAdvance(),也可以批量遍历forEachRemaining()
  • characteristics():返回分割器和数据元素的属性,所有可能的属性有ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT, and SUBSIZED,这些属性可以用来控制,专门化或简化计算
  • estimateSize():剩余元素数量的估计值
  • trySplit():数据分割,返回一个新的Spliterator迭代器,分出一半待遍历的元素由新的Spilterator遍历
  • 不是线程安全的,并行算法应该确保单个Spliterator一次只被一个线程使用

具体实现有ArrayListSpliteratorIteratorSpliterator等,底层还是数组和Iterator,例如ArrayListSpliterator的构造函数

        ArrayListSpliterator(ArrayList list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // 要遍历的ArrayList
            this.index = origin; // 当前索引
            this.fence = fence; // 结束位置,比最后一个元素索引大1
            this.expectedModCount = expectedModCount; //确保没有发生修改,对应于modCount变量
        }

中间操作

操作 描述
Stream filter(Predicate predicate) 过滤元素,返回过滤后的元素
Stream map(Function mapper) 对每个元素执行给定的函数,从而变成一个新的集合
Stream flatMap(Function> mapper) flatMap 扁平映射,流中的每个元素转换为一个新的流,最终合并为一个新的流
Stream distinct() 去重复,根据equals()
Stream sorted(Comparator comparator) 排序
Stream peek(Consumer action) 主要用来调试,查看流过的元素
Stream limit(long maxSize) 最长截取前边maxSize个元素
Stream skip(long n) 跳过前n个

终结操作

操作 描述
void forEach(Consumer action) 每一个元素都执行相应的表达式
Object[] toArray() 使用流的元素创建一个数组
T reduce(T identity, BinaryOperator accumulator) 元素聚合为一个汇总值
R collect(Collector collector) 将流的元素聚合到一个容器中
Optional min(Comparator comparator) 返回最小值
Optional max(Comparator comparator); 返回最大值
long count() 数目
boolean {any,all,none}Match(Predicate predicate) 返回流是否任何/所有/没有的元素与提供的预期相匹配。
Optional findFirst() 返回流的第一个元素(如果有)
Optional findAny() 返回流的任何元素(如果有)

你可能感兴趣的:(Java 集合的流式操作)