惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Stack Overflow Blog
Stack Overflow Blog
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
L
LangChain Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
Y
Y Combinator Blog
月光博客
月光博客
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
小众软件
小众软件
H
Help Net Security
Last Week in AI
Last Week in AI
B
Blog RSS Feed
宝玉的分享
宝玉的分享
N
Netflix TechBlog - Medium
博客园 - 叶小钗
The GitHub Blog
The GitHub Blog

犀利豆的博客

《SRE google 运维解密》读书笔记 (六) 《SRE google 运维解密》读书笔记 (五) 《SRE google 运维解密》读书笔记 (四) 《SRE google 运维解密》读书笔记 (三) 《SRE google 运维解密》读书笔记 (二) 《SRE google 运维解密》读书笔记 (一) 2021 总结 终于有一个 Java 可以用的微信机器人了 Vertx入门到实战—实现钉钉机器人内网穿透代理 钉钉机器人回调内网穿透代理--使用篇 周末补习(一)trie 树 那些有趣的代码(三)--勤俭持家的 ArrayList 那些有趣的代码(二)--偏不听父母话的 Tomcat 类加载器 那些有趣的代码(一)--有点萌的 Tomcat 的线程池 从需求第三定律说起--为什么知乎的回答质量下降了 如何利用 Spring Hibernate 高级特性设计实现一个权限系统 居然有人能忘记吃饭?写个微信机器人提醒他 我的2018年总结 从 LongAdder 中窥见并发组件的设计思路 徒手撸框架--实现 RPC 远程调用 我的写作工具链 Java 渲染 docx 文件,并生成 pdf 加水印 撸码的福音--变量名生成器的实现 Raft 协议学习笔记 dubbo 源码学习(一)开篇 Redis 命令的执行过程 Redis 中的事件驱动模型 Redis 数据库、键过期的实现 Redis 的基础数据结构(三)对象 Redis 的基础数据结构(二) 整数集合、跳跃表、压缩列表
JAVA 8入门(二)流
Zhengxin Diao · 2017-10-25 · via 犀利豆的博客

1.简单使用

书接上回,我们这一讲要讨论 JAVA 8 的新的 API 流。如果我们有这样一个需求,需要挑选出菜谱里面卡路里小于1000,且卡路里排名前三的菜品的名称。

如果使用JAVA 7的传统写法我们应该这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public List<String> findDish(List<Dish> menu){
List<Dish> lowCaloricDishes = new ArrayList<>();
for (Dish dish : lowCaloricDishes) {
if(dish.getCalories() < 1000 ){
lowCaloricDishes.add(dish);
}
}

Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getCalories(),o2.getCalories());
}
});

List<Dish> result = lowCaloricDishes.subList(0,3);
List<String> resultName = new ArrayList<>();

for (Dish dish : result) {
resultName.add(dish.getName());
}
return resultName;
}

通过上面的例子我们可以看到我们使用了很多的中间变量,来存储中介结果,lowCaloricDishes、result、resultName。相当繁琐。如果我们使用 JAVA 8的流的方式来实现代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public List<String> findDishWithSteam(List<Dish> menu){


List<String> resultName = menu.stream()
.filter(dish -> dish.getCalories()<1000)
.sorted(Comparator.comparing(Dish::getCalories))
.limit(3)
.map(Dish::getName)
.collect(Collectors.toList());

return resultName;
}

如果我们把 steam() 变换为 parallelStream(),整个操作就变成并行的。代码十分优雅,想到每天我们处理那么多的集合,反正我已经迫不及待的想使用上`JAVA 8了。

2. 流的定义

到底什么是流?书上给的定义是 “从支持数据处理操作的源生成的元素序列”

  • 元素序列 和集合一样,我们可以理解为是一堆有序的值。但是集合侧重的是数据,流侧重的是计算。
  • 源 流会使用一个提供数据的源。比如 menu.stream()中,meun就是这个流的源。
  • 数据处理操作 流的数据处理功能类似,数据库的操作,同时也支持函数式编程中的操作。

我们看看接口java.util.stream.Stream都有一些什么方法:

stea

我们可以看到,之前我们在上一个例子里面使用的方法,filter()sorted()limit()map() 的返回值也是一个流Stream,也就是说我们可以,把所有的操作串起来。这个是流的一个特点流水线

还有一个特点就是内部迭代,与集合的迭代不同,流的迭代不是显式的迭代。

3. 流的基本操作

1. 筛选和切片

  1. 筛选filter()

    所谓筛选就是找出符合条件的元素,filter()接受一个返回boolean类型的函数。
    比如:

    1
    filter(dish -> dish.getCalories()<1000)
  2. 去重distinct()

    去重的方法我们可以类比SQL 语句中的 distinct

  3. 截断limit()

    同样类似 SQL里面的 limit,接受一个 Long 值。返回流中的前n个元素。

  4. 跳过skip()

    跳过前n个元素。很好理解

2. 映射

  1. map()

    map对流中的每一个元素应用函数,可以理解为将元素转化为另一个元素。

    1
    .map(Dish::getName)
  2. flatmap()

    flatmap方法就是把流中的每一个元素都装换为另外一个流,然后合并为一个流。

    1
    2
    3
    4
    5

    List<List<String>> lists = new ArrayList<>();
    lists.add(Arrays.asList("apple", "click"));
    lists.add(Arrays.asList("boss", "dig", "qq", "vivo"));
    lists.add(Arrays.asList("c#", "biezhi"));

找出所有大于两个字符的元素:

1
2
3
4
lists.stream()
.flatMap(Collection::stream)
.filter(str -> str.length() > 2)
.count();

3. 查找匹配

match、anyMatch、allMatch、noneMatch
以上方法都能返回一个boolean类型。

1
boolean hasLowCalories = mune.stream().anyMatch(dish -> dish.getCalories()<1000)

4. 归约

reduce(T,BinaryOperator<T>)

reduce 操作是 反复结合每一个元素,直到流被归约成一个值。其中:

  • T 指的是初始值;
  • BinaryOperator<T> 两个元素结合起来获得一个元素,举个例子:
    Lamdba: (a,b)-> a + b

所以给定一个 List<Integer> 计算出和所有int 的和:

1
int sum = list.stream().reduce(0,(a,b)-> a + b);

或者:

1
int sum = list.stream().reduce(0,Integer::sum);

5. 收集数据

一顿操作之后,我们需要把数据收集起来。就需要使用collect()方法。

1
2
Map<String, Integer> map = meun.stream()
.collect(Collectors.toMap(Dish::getName, Dish::getCalories));