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

989095553c39c3942cc9754053e6f5a2.png


我们是否一样 ?

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

ac6a56f7f999698b8bc7aaec917c722f.png

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

ed88f4ddce5415c5e6ae67d636be42a5.png

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

但,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。 因此,Stream流的一哥地位,并非空穴来风

接下来,硬核 SAO 操作,别眨眼82bfaad123c9387d9f03006024a319f5.png

为什么需要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流,至于何地

39a67b8e36dc9d10049b699dfc84ee92.png

体验哈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,爱了,爱了

97f7fd0cdd476b751f1aae50f44bc2a6.png

您也为这就是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 流,今就到这,下回见

ca3fbfc07f4f192972e44ad5ccf9f028.png

后记

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

好文推荐

  • 两年了,才知道如何实现多线程 ,哎
  • 答应我,别再if/else校验请求参数了可以吗
  • 浅聊过滤器 + 拦截器 + JWT
  • 微信小程序支付 + 公众号支付 (含源码)
  • 微信公众号授权+获取用户信息+jwt登录 (含源码)
  • 微信小程序授权+获取用户手机号+jwt登录 (含源码)

de8e1ddb5b00f5bab9b6c76493586844.png

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

小声BB

  • 中国传统文化,先仔细看,若有用,再点“ 赞 ”和“ 在看 ”

  • 更多幽默、风趣好文,尽在“CodeCow·程序牛”公众号

8bb9ec01e3d93d9c16dd2d8539408dcc.png

ba236afb88c582891e16ce9b3adb79ab.png Stream流,您会了吗?
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值