恕我直言,我怀疑你没怎么用过Stream流

简书.jpg

文:恕我直言,我怀疑你没怎么用过Stream流
注:中国传统文化,先仔细看,若有用,再点赞, 给自己一点思考的时间
注:微信搜索:CodeCow,关注这个非常 SAO 的程序员

我们是否一样 ?

想当年,小编在自学Java语言看书时,关于 “Stream流” 这一块的知识点可能都有点 “轻敌” ,觉得这块内容 “ so easy ”非常简单,一眼而过。

d5fd2455a0c297c2e57c85fd2d9ad6ad - 副本.jpg

殊不知,捡了芝麻,丢了西瓜;并且在小编代码中,也从未有过“Stream流” 地位可言;却浑然不知,java8的一哥“Stream流”,在旁暗自嘲讽 “ 这TM是谁,太菜了 ” 。

就拿小编上篇文章《两年了,才知道如何实现多线程,哎 》来讲,也是一堆连环 for 循环的SAO操作,何曾想过Stream流的感受

java 8 一哥 ?

在Java 8中,得益于 Lambda 所带 来的 函数式编程,应运而生了一个全新的概念——Stream流,用于解决已有集合类库既有的弊端。

首先

关于Stream流上的操作,大体可以分为两种:

  • 中间操作(Intermediate),其返回结果都是Stream,故可以多个中间操作叠加;
  • 终止操作(Terminal),其返回结果是我们最终需要的数据,故只能有一个终止操作

其次

Stream流是一个来自数据源的元素队列,例如

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组 等。

再者

Stream流和以前的 Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining:中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。

最后

喽一眼Stream流的接口继承关系
[图片上传失败...(image-b7eb65-1596705940785)]

所以,当我们使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结果

但,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以 像链条一样排列,变成一个管道。

注意:“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何 元素(或其地址值)。

因此,Stream流的一哥地位,并非空穴来风

接下来,硬核SAO操作,别眨眼
[图片上传失败...(image-a750dd-1596705940785)]

为什么需要Stream流

常用的for循环它不香吗?为啥非得用Stream流?

举个简单的例子:

学生对象:

@Data
@AllArgsConstructor
public class Student {

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "性别(1-男,2-女)")
    private Integer sex;
}

学生对象集合

public class StreamDemo {

    public static void main(String[] args) {
        // 测试数据
        List<Student> studentList = Lists.newArrayList();
        studentList.add(new Student("CodeCow", 18, 1));
        studentList.add(new Student("小明", 30, 1));
        studentList.add(new Student("小猪", 40, 2));
        studentList.add(new Student("小狗狗", 50, 2));
    }
}
        

假如,现有需求:筛选所有姓小的同学,并且名字有三个字,最后对结果进行打印输出

小编很幸运,曾见过这样的SAO代码,可谓 “猛龙过江”,管你三七二十一,上来先整几个for循环再说;

public static void main(String[] args) {

    //第一步:找出姓小的同学,放在list1 
    List<Student> list1 = Lists.newArrayList();
    for (Student student : studentList) {
        if (student.getName().startsWith("小")) {
            list1.add(student);
        }
    }
    //第二步:找出名字有三个字的同学,放在list2
    List<Student> list2 = Lists.newArrayList();
    for (Student student : list1) {
        if (student.getName().length() == 3) {
            list2.add(student);
        }
    }
    //第三步:打印结果
    for (Student student : list2) {
        System.out.println(student);
    }
}

接下来,我们Debug运行下,看下结果:

Student(name=小狗狗, age=50, sex=2)

卧CAO,学生倒是赛选出来了,但是,现在赛选 条件只有三个,当条件有几十个时,那几十个for循环,不累吗,那可以说是非常酸爽了……

再者,你将Java 8 的一哥——stream流,至于何地
[图片上传失败...(image-f0a1c5-1596705940785)]

体验哈Stream流的更优写法

大家肯定都知道Lambda吧,Java 8的Lambda让我们可以更加专注于做什么(What),而不是怎么做(How)

这点小编也在上篇文章《两年了,才知道如何实现多线程,哎 》中结合“线程 + 匿名内部类” 进行了对比说明。有空可以看下

现在,我们体会下Stream流的优雅:

public static void main(String[] args) {

   studentList.stream()
        .filter(i -> i.getName().startsWith("小"))//过滤出姓小的同学
        .filter(i -> i.getName().length() == 3) //过滤出名字有三个字的同学
        .forEach(System.out::println); //打印结果
}

再次Debug运行下,看下结果:

Student(name=小狗狗, age=50, sex=2)

不难发现,区区3行代码,运行结果也一样;同时,顺带解决了上面的SAO操作, 他不香吗?

总结下,为什么很香

  • 第一点:可以清楚地知道我们要对一个数据集做何种操作,可读性贼强(就三行,读不明白 ?)
  • 第二点:可以很轻松地获取并行化Stream流,不用自己编写多线程代码(阿牛上篇文章就是最好的证明!!)
  • 第三点:可以让我们更加专注于业务逻辑 (还用考虑用几个for循环吗!!)。

简而言之,Stream,爱了,爱了

在这里插入图片描述

您也为这就是Stream流的全部吗,“No,No,No

接下来,咋们看下Stream流 风SAO 集合

了解下Stream流更多SAO操作

需求1:获取姓小同学的集合

public static void main(String[] args) {

    List<Student> list = studentList.stream()
        .filter(i -> i.getName().startsWith("小"))
        .collect(Collectors.toList());
}

结果为:

[
Student(name=小明, age=30, sex=1), 
Student(name=小猪, age=40, sex=2), 
Student(name=小狗狗, age=50, sex=2)
]

需求2:获取姓小的同学,并且年龄大于30的集合

public static void main(String[] args) {

    List<Student> list = studentList.stream()
        .filter(i -> i.getName().startsWith("小") && i.getAge() >30)
        .collect(Collectors.toList());
}

结果为:

[
Student(name=小猪, age=40, sex=2), 
Student(name=小狗狗, age=50, sex=2)
]

需求3:获取姓名为“小明”的同学,的集合

public static void main(String[] args) {

    List<Student> list = studentList.stream()
        .filter(i -> i.getName().equals("小明"))
        .collect(Collectors.toList());
}

结果为:

[Student(name=小明, age=40, sex=1)]

需求4:获取所有同学姓名的集合

public static void main(String[] args) {

    List<String> list = studentList.stream()
        .map(Student::getName)
        .collect(Collectors.toList());
}

结果为:

[CodeCow, 小明, 小猪, 小狗狗]

需求5:根据学生年龄进行升序排序

public static void main(String[] args) {

    List<Student> list = studentList.stream()
        .sorted(Comparator.comparing(Student::getAge))
        .collect(Collectors.toList());
}

结果为:

[
Student(name=CodeCow, age=18, sex=1), 
Student(name=小明, age=40, sex=1), 
Student(name=小猪, age=50, sex=2), 
Student(name=小狗狗, age=50, sex=2)
]

需求6:根据学生年龄进行降序排序

public static void main(String[] args) {

    List<Student> list = studentList.stream()
        .sorted(Comparator.comparing(Student::getAge).reversed())
        .collect(Collectors.toList());
}

结果为:

[
Student(name=小猪, age=50, sex=2), 
Student(name=小狗狗, age=50, sex=2), 
Student(name=小明, age=40, sex=1), 
Student(name=CodeCow, age=18, sex=1)
]

需求7:distinct 去重

public static void main(String[] args) {

    List<Integer> integers = Lists.list(30, 40, 10, 20, 20, 10, 50, 20);
    List<Integer> collect = 
            integers.stream().distinct().collect(Collectors.toList());
    System.out.println(collect);//[30, 40, 10, 20, 50] 去重结果
}

需求8:找最小值 min,总数量 count

public static void main(String[] args) {

    List<Integer> integers = Lists.list(30, 40, 10, 20, 20, 10, 50, 20);
    Integer integer1 = integers.stream().min(Integer::compareTo).orElse(-1);
        System.out.println(integer1); //10 最小值
        long count = integers.stream().count();
        System.out.println(count);//8 总数量
}

浅聊 Java 8 Stream 流,今就到这,下文见 _

在这里插入图片描述

后记

好啦,今就先聊到这里吧,本文仅仅是 抛砖引玉 而已,使用了 Java 8 Stream流 和大家聊了聊,打了个样;且并非Stream流所有特性,这只是其 冰山一角;下文见

★★ 好文推荐 ★★

小声BB

  • 中国传统文化,先仔细看,若有用,再点赞, 给自己一点思考的时间
  • 更多幽默、风趣好文,尽在“ CodeCow ” , WX搜索 CodeCow,可以看看

《 Java如海,学习作舟,泛舟于海,方知Java之宽阔 》

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