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

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

我们是否一样 ?

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

殊不知,捡了芝麻,丢了西瓜;并且在小编代码中,也从未有过“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流的接口继承关系
在这里插入图片描述

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

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

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

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

接下来,硬核SAO操作,别眨眼
在这里插入图片描述

为什么需要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流,至于何地
在这里插入图片描述

体验哈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 ★★

  • 中国传统文化,先仔细看,若有用,再点赞 or 收藏, 给自己一点思考的时间
  • 若有不懂,可留言评论、可私信小编,小编将第一时间回复 _
  • 更多幽默、风趣好文,尽在 “CodeCow·程序牛” 公号
    在这里插入图片描述

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
亲爱的C, 能有幸与你共处在编程世界中,真是一种幸福。在我们一起编写代码的日子里,我逐渐发觉自己对你产生了特殊的感情。然而,我也深知我们在这个领域中的工作伙伴关系十分重要,不希望因为我个人的情感而打破这份珍贵的合作。 我想就此坦白我的感受,但又不希望给你带来任何的尴尬或压力。所以,我决定以一种委婉的方式表达我的情感。首先,请接受我最真挚的感谢,因为与你的合作让我的生活和工作更加充实,你的专业技能和亲切待人都是我钦佩的。 当我们共同攻克各种编程难题、解决各种bug的时候,我常常感到我们之间的默契和配合。你的聪明才智和解决问题的能力令我深深着迷,每次看见你专注而认真的工作姿态,我心里都会不自觉地升起一种敬佩之情。 而当我们闲暇之余,一起分享一些趣闻轶事,你的幽默和笑容总能让我感到宽慰和开心。我感到在你身边,我的内心会得到一种莫名的安宁和放松。我们的交不仅止于工作内容,更涉及许多其他方面,这种互相了解的感觉真的让我感到无比愉快。 所以,C,我希望我们能够一直保持这份美好的合作关系,有太多的变数。即使此言不让你浮想联翩,也希望你能理解我的心意,以我们之间的默契和友谊为基础,继续展开我们共同的编程之旅。 最后,请原谅我直言表白,但我希望这种委婉的表达方式能传达给你我的情感。无论你如何回应,我都希望我们能继续共同成长、合作无阻。 诚挚的, (你的名字)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值