Java8 stream

  • stream是什么?

可以把Stream当成一个高级的Iterator(迭代器)。普通的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,stream将会开几个线程并行执行这些操作.

  • 举个栗子

List<String> list = Arrays.asList("one","two","three", "four","five");
list.stream().filter(str -> str.length() > 3).forEach(System.out::println);
使用stream的一般过程

Java stream的使用过程可以分为三个步骤

  1. 创建stream
  2. 转换stream(每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换))
  3. 汇聚操作(对Stream进行Reduce操作,获取想要的结果)
  • Java stream的使用过程

创建stream
  1. 通过stream类的静态方法
  • Stream.of(创建一个定长的strea)
Stream<String> stream = Stream.of("1","2","3");
  • Stream.generate(创建一个无限长的stream)
Stream<Double> stream = Stream.generate(Math::random);
  • Stream.iterate(也是生成一个无限长的stream)
Stream<Integer> stream = Stream.iterate(1, item -> item + 1);
  1. 通过 collection的 stream()方法
    Collection实现了stream()方法,它的子类(比如list,map)都拥有该方法.
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

使用:

List list = new ArrayList(Arrays.asList("1", "2", "3"));
Stream<String> stream = list.stream();
转换stream
  1. distinct (对重复的流元素去重)
List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
list.stream().distinct().forEach(System.out::println);

出来的结果是: 1,3,5,7,9 ; 1,3被去重了

  1. filter (过滤器:只返回符合要求的元素)
        List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
        list.stream().filter(i -> i > 4).forEach(System.out::println);

在这个例子中, i <= 4 的元素都被剔除掉了,只打出 5,7,9三个元素

  1. map(原stream的元素经过计算转变成为另一个stream)
        List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
        list.stream().map(i -> i + 4).forEach(System.out::println);

本来应该输出1,1,3,3,5,7,9 ; 但是经过i + 4之后,变成输出 4,4,7,7,9,11,13

  1. peek(peek方法方法会使用一个Consumer消费流中的元素,但是返回的流还是包含原来的流中的元素)
List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
list.stream().peek(System.out::println).map(i -> i + 4).count();

peek方法返回void

  1. limit(限制返回多少个元素)
        List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
        list.stream().limit(2).forEach(System.out::println);

本来应该输出全部元素的,但是实际上只输出2个元素

  1. skip(和limit是相对的操作,limit是保存前n个元素,skip是跳出前n个元素)
        List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
        list.stream().skip(2).forEach(System.out::println);

实际上输出3,3,5,7,9

  1. sorted(对元素进行排序)
 List<Integer> list = new ArrayList(Arrays.asList(1, 1, 11, 3, 3, 5, 7, 9));
 list.stream().sorted((x, y) -> y - x).forEach(System.out::println);

倒序
PS: 我们对stream进行N次转换, 以为一共执行了 N个循环,实际上只进行了一次循环

汇聚操作

汇聚操作(也称为折叠)接受一个元素序列为输入,反复使用某个合并操作,把序列中的元素合并成一个汇总的结果.。比如查找一个数字列表的总和或者最大值,或者把这些数字累积成一个List对象

汇聚操作的分类

  1. 可变汇聚(把输入的元素们累积到一个可变的容器中,比如Collection或者StringBuilder)
  • 原生collect
    <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
    看一个栗子: 下面代码的作用是把猫的名字提取出来,放到一个新list里面
List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
cats.stream().collect(ArrayList::new, (list, item) -> list.add(item.getName()), (list1, list2) -> list1.addAll(list2)).forEach(System.out::println);

第一个函数生成一个新的ArrayList实例
第二个函数接受两个参数,第一个是前面生成的ArrayList对象,二个是stream中包含的元素,函数体就是把stream中的元素加入ArrayList对象中。第二个函数被反复调用直到原stream的元素被消费完毕
第三个函数也是接受两个参数,这两个都是ArrayList类型的,函数体就是把第二个ArrayList全部加入到第一个中(为什么会有第三步呢?因为第二步他可能是并行操作的,即第二步会产生多个list,第三步把第二步中产生的所有list都添加到新的一个list中)

  • Collectors(工具类)
    如果你感觉原生的collect很难用,你可以用collectors来实现.
        List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
        cats.stream().map(cat -> cat.getName()).collect(Collectors.toList());
  1. 其它汇聚
  • count 计算stream中的元素的个数
  • allMatch 是不是stream中所有元素都满足给定的匹配条件
  • findFirst 查找stream的第一个元素
List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
Optional<String> first = cats.stream().map(cat -> cat.getName()).findFirst();
System.out.println(first.get());

findFirst会返回一个optional对象,optional的用法后面再说

  • max 和 min
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elem...
    kechao8485阅读 1,235评论 0 9
  • 本文将会详细讲解Stream的使用方法(不会涉及Stream的原理,因为这个系列的文章还是一个快速学习如何使用的)...
    光剑书架上的书阅读 5,541评论 0 16
  • 前言: 讲Stream之前,先来用个小需求带入本文。毕竟代码看的最清楚。 正文: 项目某个页面有个需求,将关键词和...
    T9的第三个三角阅读 2,390评论 1 9
  • 这篇关于java stream的文章写的特别好,转载一下,以备自己查看。转载自Java 8 中的 Streams ...
    小白小白啦阅读 510评论 0 2
  • 观音上师:“修忍辱功德或福报,也要回向给敌人,因为敌人不惜因果来骂你,让你有修忍辱的机会,所以你要回向给他,没有一...
    Drenched_belief阅读 793评论 0 0