Java8のStream学习

来源:互联网 发布:4万亿救市的后果知乎 编辑:程序博客网 时间:2024/05/15 05:38
转载自:http://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

       JDK中已经增加了一个新包java.util.stream,能够使用Java8集合类库执行类似filter/map/reduce的操作。这个流式API使我们能在数据流之上编写串行或者并行的操作。
       Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样就可以将多个操作依次串起来。 Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set,Map不支持。Stream的操作可以串行执行或者并行执行。

       Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。
       当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。

流的操作类型

       流的操作类型分为两种:
       Intermediate(中间操作):一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

       Terminal(末端操作):一个流有且仅有一个terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个或者导致一个副作用(side effect)。


       在对于一个 Stream 进行多次转换操作(Intermediate 操作),每次都对 Stream 的每个元素进行转换,而且是执行多次,这样时间复杂度就是 N(转换次数)个for循环里把所有操作都做掉的总和吗?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。可以这样简单的理解,Stream 里有个操作函数的集合,每次转换操作就是把转换函数放入这个集合中,在Terminal操作的时候循环 Stream 对应的集合,然后对每个元素执行所有的函数。

       还有一种操作被称为 short-circuiting(短循环)。指:
           对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的Stream,但返回一个有限的新 Stream。
           对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
       当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。

       接下来,当把一个数据结构包装成 Stream 后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下:
Intermediate(中间操作):
       map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal(末端操作):
       forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting(短循环):
       anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

流的使用详解

流的构造与转换

// 1. Individual valuesStream stream = Stream.of("a", "b", "c");// 2. ArraysString [] strArray = new String[] {"a", "b", "c"};stream = Stream.of(strArray);stream = Arrays.stream(strArray);// 3. CollectionsList<String> list = Arrays.asList(strArray);// 串行stream = list.stream();// 并行Stream<String> parallelStream = list.parallelStream();

流的操作

map/flatMap
它的作用就是把 input Stream 的每一个元素,映射成output Stream 的另外一个元素。
Stream.of("one", "two", "three", "four").map(String::toUpperCase).forEach(s -> System.out.println(s));Stream.of("one", "two", "three", "four").map(s->s.substring(0, 2)).forEach(s -> System.out.println(s));
从上面例子可以看出,map 生成的是个 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素。还有一些场景,是一对多映射关系的,这时需要 flatMap。

filter
filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。即排除所有不满足条件的元素。

forEach
       forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。当需要为多核系统优化时,可以 parallelStream().forEach(),只是此时原有元素的次序没法保证,并行的情况下将改变串行时操作的行为,此时 forEach 本身的实现不需要调整。但一般认为,forEach 和常规 for循环的差异不涉及到性能,它们仅仅是函数式风格与传统 Java 风格的差别。
       另外一点需要注意,forEach 是terminal(末端)操作,因此它执行后,Stream 的元素就被“消费”掉了,无法对一个Stream 进行两次 terminal运算。下面的代码是错误的,会报java.lang.IllegalStateException: stream has already been operated upon or closed异常:
stream.forEach(System.out::print);stream.forEach(System.out::print);

peek
对每个元素执行操作并返回一个新的Stream。

reduce
       这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。
// 字符串连接,concat = "ABCD"String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);// 求和,sumValue = 10, 有起始值int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);// 求和,sumValue = 10, 无起始值,返回的是 Optional。int sum = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();

limit/skip
limit返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素(它是由一个叫 subStream 的方法改名而来)。

sorted
       对Stream 的排序通过 sorted 进行,它比数组的排序更强之处在于你可以首先对 Stream 进行各类 map、filter、limit、skip 甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。我们对清单 14 进行优化:

Match
Stream 有三个 match 方法,从语义上说:
       allMatch:Stream 中全部元素符合传入的 predicate,返回 true
       anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
       noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
它们都不是要遍历全部元素才能返回结果。例如 allMatch 只要一个元素不满足条件,就 skip 剩下的所有元素,返回 false。








0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果5s指纹失灵怎么办 学生赌博输了3万怎么办 电脑录屏没有声音怎么办 别人说你没有他美怎么办 没有你我怎么办歌词是什么意思 要是没有他我怎么办啊歌词 用喀秋莎保存的视频黑屏怎么办 电脑杀毒之后开不了机怎么办 夫妻离婚分房分车怎么办 请的护身符丢了怎么办 老车轻微烧机油怎么办 电脑下软件变卡怎么办 机械表日历偏了怎么办 子宫内膜异位痛经怎么办 凉着了坏肚子怎么办 昆虫叮咬后疼痛起水泡怎么办 每次来月经都痛经怎么办 人左肩的灯灭了怎么办 香港超过7天了怎么办? 手机拍完照图像是倒的怎么办 地下城金币邮寄卡了怎么办 wow7.3打团本卡怎么办 上古卷轴5出bug怎么办 苹果手机打游戏太卡怎么办 梦幻将军令换了怎么办 手机丢了将军令怎么办 大军之印放弃了怎么办 联想一体机进入界面就死机怎么办 nmd袜子鞋露脚趾怎么办 生意不顺意志崩溃了怎么办 笔记本突然卡住不动了怎么办 指定货代费用高怎么办 空运舱单上的收货人错了怎么办? 被诚信贷骗了怎么办 原户主不迁户口怎么办 二手房原房主没迁走怎么办 办退工没有就失业证怎么办 消防队教导员插手商场翘柜台怎么办 调动工作原单位领导不放人怎么办 脚碰了一下肿了怎么办 六十岁的犯人身体有病怎么办