Board logo

标题: Java 8 的 Lambda 表达式和流处理(2)流 [打印本页]

作者: look_w    时间: 2018-12-7 19:58     标题: Java 8 的 Lambda 表达式和流处理(2)流

流Java 8 中的流表示的是元素的序列。流中的元素可能是对象、int、long 或 double        类型。流作为一个高层次的抽象,并不关注流中元素的来源或是管理方式。流只关注对流中元素所进行的操作。当流与函数式接口和 Lambda        表达式一同使用时,可以写出简洁高效的数据处理代码。下面介绍几个与流相关的基本概念。
顺序执行和        并行执行流的操作可以顺序执行或并行执行, 后者可以获得比前者更好的性能。但是如果实现不当,可能由于数据竞争或无用的线程同步,导致并行执行时的性能更差。一个流是否会并行执行,可以通过其方法        isParallel() 来判断。根据流的创建方式,一个流有其默认的执行方式。可以使用方法 sequential() 或 parallel() 来将其执行方式设置为顺序或并行。
相遇顺序一个流的相遇顺序(encounter order)是流中的元素被处理时的顺序。流根据其特征可能有,也可能没有一个确定的相遇顺序。举例来说,从 ArrayList        创建的流有确定的相遇顺序;从 HashSet        创建的流没有确定的相遇顺序。大部分的流操作会按照流的相遇顺序来依次处理元素。如果一个流是无序的,同一个流处理流水线在多次执行时可能产生不一样的结果。比如 Stream 的        findFirst() 方法获取到流中的第一个元素。如果在从 ArrayList 创建的流上应用该操作,返回的总是第一个元素;如果是从 HashSet        创建的流,则返回的结果是不确定的。对于一个无序的流,可以使用 sorted 操作来排序;对于一个有序的流,可以使用 unordered() 方法来使其无序。
Spliterator所有的流都是从 Spliterator 创建出来的。Spliterator 的名称来源于它所支持的两种操作:split 和 iterator。Spliterator 可以看成是        Iterator 的并行版本,允许通过对流中元素分片的方式来切分数据源。使用其 tryAdvance 方法来顺序遍历元素,也可以使用 trySplit 方法来创建一个新的        Spliterator 对象在新划分的数据集上工作。Spliterator 还提供了 forEachRemaining 方法进行批量顺序遍历。可以使用 estimateSize        方法来查询可能会遍历的元素数量。一般的做法是先使用 trySplit 切分数据源。当元素数量足够小时,使用 forEachRemaining        来对分片中的全部元素进行处理。这也是典型的分治法的思路。
每个 Spliterator 可以有一系列不同的特征,可以通过 characteristics 方法来查询。一个 Spliterator        具备的特征取决于其数据源和元素。所有可用的特征如下所示:
Spliterator 需要绑定到流之后才能遍历其中的元素。不同的 Spliterator 实现可能有不同的绑定时机。如果一个 Spliterator        是延迟绑定的,那么只有在进行首次遍历、首次切分或首次查询大小时,才会绑定到流上;反之,它会在创建时或首次调用任何方法时绑定到流上。绑定时机的重要性在于,在绑定之前对流所做的修改,在        Spliterator 遍历时是可见的。延迟绑定可以提供最大限度的灵活性。
有状态和无状态操作 流操作可以是有状态或无状态的。当一个有状态的操作在处理一个元素时,它可能需要使用处理之前的元素时保留的信息;无状态的操作可以独立处理每个元素,举例来说:
Stream<T> 是表示流的接口,T 是流中元素的类型。对于原始类型的流,可以使用专门的类 IntStream、LongStream 和        DoubleStream。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0