尚学堂百战程序员之Stream API

尚学堂百战程序员之Stream API
2018年06月14日 10:20 独一无二的楠竹

Java8中有两大最为重要的特性。

1)Lambda表达式,已经学习过了;2)Stream API (java.util.stream.*包下)

说到Stream便容易想到I/O Stream,而实际上我们这里讲的Stream它是Java8中对数据处理的一种抽象描述;

我们可以把它理解为数据的管道,我们可以通过这条管道提供给我们的API很方便的对里面的数据进行复杂的操作!比如查找、过滤和映射(类似于使用SQL);

更厉害的是可以使用Stream API来并行执行操作;简而言之,Stream API提供了一种高效且易于使用的处理数据的方式,解决了已有集合类库操作上的弊端。

●注意:1.请暂时忘记对传统IO流的固有印象!2.Stream接口继承关系

图中4种stream接口继承自BaseStream,其中IntStream, LongStream, DoubleStream对应三种基本类型(int, long, double,注意不是包装类型),Stream对应所有剩余类型的stream视图。为不同数据类型设置不同stream接口,可以提高性能,并针对不同数据类型提供不同方法实现。那什么不把IntStream等设计成Stream的子接口?毕竟这接口中的方法名大部分是一样的。答案是这些方法的名字虽然相同,但是返回类型不同,如果设计成父子接口关系,这些方法将不能共存,因为Java不允许只有返回类型不同的方法重载。

传统集合操作vs Stream API操作

传统方式遍历集合

几乎所有的集合(如Collection接口或Map接口等)都支持直接或间接的遍历操作。而当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。例如:

List

list = new ArrayList();

list.add("马云");

list.add("马化腾");

list.add("李彦宏");

list.add("雷军");

list.add("刘强东");

for (String name : list) {

System.out.println(name);

}

这是一段非常简单的集合遍历操作:对集合中的每一个字符串都进行打印输出操作。

循环遍历的弊端

Java 8的Lambda让我们可以更加专注于做什么(What),而不是怎么做(How),这点此前已经结合匿名内部类进行了对比说明。现在,我们仔细体会一下上例代码,可以发现:

for循环的语法就是“怎么做”for循环的循环体才是“做什么”(这才是我们要完成的目标!)

如果觉得上面那样的for循环也无所谓的话,我们来完成几个需求:

1)找出姓马的;2)再从姓马的中找到名字长度等于3的。

如何实现?在Java 8之前的做法可能为:

@Test

public void testWithFor() throws Exception {

List

list = new ArrayList();

list.add("马云");

list.add("马化腾");

list.add("李彦宏");

list.add("雷军");

list.add("刘强东");

List

maList = new ArrayList();

for (String name : list) {

if (name.startsWith("马")) {

maList.add(name);

}

}

List

length3List = new ArrayList();

for (String name : maList) {

if (name.length() == 3) {

length3List.add(name);

}

}

for (String name : length3List) {

System.out.println(name);

}

}

这段代码中含有三个循环,每一个作用不同:

1)首先筛选所有姓张的人;2)然后筛选名字有三个字的人;3)最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使用另一个循环从头开始。那Stream能给我们带来怎样更加优雅的写法呢?

Stream的优雅写法

下面来看一下如果使用Java 8的Stream API来实现将有多么的优雅:

@Test

public void testWithStream() throws Exception {

List

list = new ArrayList();

list.add("马云");

list.add("马化腾");

list.add("李彦宏");

list.add("雷军");

list.add("刘强东");

list.stream()

.filter(s -> s.startsWith("马"))

.filter(s -> s.length() == 3)

.forEach(System.out::println);

}

使用Stream API将我们真正想要做的事情直接体现在代码中。直接阅读代码的字面意思即可完美展示我们要做的事:

获取流、过滤出姓马的、过滤出名字长度为3的、逐一打印。

后记:对于大部分转行的人来说,找机会把自己的基础知识补齐,边工作边补基础知识,真心很重要。

我们相信人人都可以成为一个IT大神,现在开始,选择一条阳光大道,助你入门,学习的路上不再迷茫。这里是北京尚学堂,初学者转行到IT行业的聚集地。"

财经自媒体联盟更多自媒体作者

新浪首页 语音播报 相关新闻 返回顶部