乐字节-Java8核心特性实战之Stream(流)


一、流的概念
- 源-流会使用一个提供数据的源,如集合、数组或输入|输出资源。
- 元素序列-就像集合一样,流也提供了一个接口,可以访问特定元素类型的一组有序值。
- 数据处理操作-流的数据处理功能支持类似于数据库的操作(数据筛选、过滤、排序等操作)。
- 流水线-多个流操作本身会返回一个流,多个操作就可以链接起来,成为数据处理的一道流水线。
二、流 & 集合
- 计算的时机


- 外部迭代与内部迭代


三、流操作过程


- 创建
- 中间处理
- 终止流
四、流的创建

4.1 集合创建流
- stream() − 为集合创建串行流。
- parallelStream() − 为集合创建并行流。
public static void main(String[] args) {
/**
* 定义集合l1 并为集合创建串行流
*/
List<String> l1 = Arrays.asList("周星驰", "周杰伦", "周星星", "周润发");
// 返回串行流
l1.stream();
// 返回并行流
l1.parallelStream();
}
4.2 值创建流
//值创建流 生成一个字符串流
Stream<String> stream = Stream.of("java8", "Spring", "SpringCloud");
stream.forEach(System.out::println);
4.3 数组创建流
- Arrays.stream(T[ ])
- Arrays.stream(int[ ])
- Arrays.stream(double[ ])
- Arrays.stream(long[ ])
/**
* 这里以int 为例 long double 不再举例
*/
Stream stream = Arrays.stream(Arrays.asList(10, 20, 30, 40).toArray());
// 根据数组索引范围创建指定Stream
stream = Arrays.stream(Arrays.asList(10, 20, 30, 40).toArray(), 0, 2);
4.4 文件生成流
stream = Files.lines(Paths.get("C:\\java\\jdbc.properties"));
System.out.println(stream.collect(Collectors.toList()));
// 指定字符集编码
stream = Files.lines(Paths.get("C:\\java\\jdbc.properties"), Charset.forName("utf-8"));
System.out.println(stream.collect(Collectors.toList()));
4.5 函数生成流
- iterate : 依次对每个新生成的值应用函数
- generate :接受一个函数,生成一个新的值
// 重100 开始 生成偶数流
Stream.iterate(100, n -> n + 2);
// 产生1-100 随机数
Stream.generate(() ->(int) (Math.random() * 100 + 1));
五、流中间操作


@Data
public class Order {
// 订单id
private Integer id;
// 订单用户id
private Integer userId;
// 订单编号
private String orderNo;
// 订单日期
private Date orderDate;
// 收货地址
private String address;
// 创建时间
private Date createDate;
// 更新时间
private Date updateDate;
// 订单状态 0-未支付 1-已支付 2-待发货 3-已发货 4-已接收 5-已完成
private Integer status;
// 是否有效 1-有效订单 0-无效订单
private Integer isValid;
//订单总金额
private Double total;
} Order order01 = new Order(1, 10, "20190301",
new Date(), "上海市-浦东区", new Date(), new Date(), 4, 1, 100.0);
Order order02 = new Order(2, 30, "20190302",
new Date(), "北京市四惠区", new Date(), new Date(), 1, 1, 2000.0);
Order order03 = new Order(3, 20, "20190303",
new Date(), "北京市-朝阳区", new Date(), new Date(), 4, 1, 500.0);
Order order04 = new Order(4, 40, "20190304",
new Date(), "北京市-大兴区", new Date(), new Date(), 4, 1, 256.0);
Order order05 = new Order(5, 40, "20190304",
new Date(), "上海市-松江区", new Date(), new Date(), 4, 1, 1000.0);
ordersList = Arrays.asList(order01, order02, order03, order04, order05);
六、筛选&切片
筛选有效订单
// 过滤有效订单
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.forEach(System.out::println);
筛选有效订单 取第一页数据(每页2条记录)
// 过滤有效订单 取第一页数据(每页2条记录)
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.limit(2)
.forEach(System.out::println);
筛选订单集合有效订单 取最后一条记录
// 过滤订单集合有效订单 取最后一条记录
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.skip(ordersList.size() - 2) // 跳过前ordersList.size()-2 记录
.forEach(System.out::println);
筛选有效订单 取第3页数据(每页2条记录)
// 过滤有效订单 取第3页数据(每页2条记录) 并打印到控制台
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.skip((3 - 1) * 2)
.limit(2)
.forEach(System.out::println);
筛选无效订单去除重复订单号记录
// 过滤无效订单 去除重复订单号记录 重写Order equals 与 hashCode 方法
ordersList.stream().filter((order) -> order.getIsValid() == 0)
.distinct()
.forEach(System.out::println);
七、映射
过滤有效订单,获取所有订单编号
//过滤有效订单,获取所有订单编号
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.map((order) -> order.getOrderNo())
.forEach(System.out::println);
过滤有效订单 ,并分离每个订单下收货地址市区信息
ordersList.stream().map(o -> o.getAddress()
.split("-"))
.flatMap(Arrays::stream)
.forEach(System.out::println);
八、排序
- 过滤有效订单 根据用户id 进行排序
//过滤有效订单 根据用户id 进行排序
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.sorted((o1, o2) -> o1.getUserId() - o2.getUserId())
.forEach(System.out::println); //或者等价写法
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.sorted(Comparator.comparingInt(Order::getUserId))
.forEach(System.out::println);
- 过滤有效订单 ,根据订单状态排序 如果订单状态相同根据订单创建时间排序
//过滤有效订单 如果订单状态相同 根据订单创建时间排序 反之根据订单状态排序
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.sorted((o1, o2) -> {
if (o1.getStatus().equals(o2.getStatus())) {
return o1.getCreateDate().compareTo(o2.getCreateDate());
} else {
return o1.getStatus().compareTo(o2.getStatus());
}})
.forEach(System.out::println); // 等价形式
ordersList.stream().filter((order) -> order.getIsValid() == 1)
.sorted(Comparator.comparing(Order::getCreateDate)
.thenComparing(Comparator.comparing(Order::getStatus)))
.forEach(System.out::println);
九、流的终止操作


十、查找与匹配
筛选有效订单 匹配是否全部为已支付订单
// 筛选有效订单 匹配是否全部为已支付订单
System.out.println("allMatch匹配结果:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.allMatch((o) -> o.getStatus() != 0)
);
筛选有效订单 匹配是否存在未支付订单
// 筛选有效订单 匹配是否存在未支付订单
System.out.println("anyMatch匹配结果:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.anyMatch((o) -> o.getStatus() == 0)
);
筛选有效订单 全部未完成订单
// 筛选有效订单 全部未完成订单
System.out.println("noneMatch匹配结果:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.noneMatch((o) -> o.getStatus() == 5)
);
筛选有效订单 返回第一条订单
// 筛选有效订单 返回第一条订单
System.out.println("findAny匹配结果:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.findAny()
.get()
);
筛选所有有效订单 返回订单总数
// 筛选所有有效订单 返回订单总数
System.out.println("count结果:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.count()
);
筛选有效订单 返回金额最大订单金额
// 筛选有效订单 返回金额最大订单金额
System.out.println("订单金额最大值:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.max(Double::compare)
.get()
);
筛选有效订单 返回金额最小订单金额
// 筛选有效订单 返回金额最小订单金额
System.out.println("订单金额最小值:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.min(Double::compare)
.get()
);
十一、归约&收集
11.1 归约
- 计算有效订单总金额
// 计算有效订单总金额
System.out.println("有效订单总金额:" +
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.reduce(Double::sum)
.get()
);
11.2 Collector数据收集
11.3 集合收集
- 筛选所有有效订单 并收集订单列表
// 筛选所有有效订单并收集订单列表
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.toList())
.forEach(System.out::println);
- 筛选所有有效订单并收集订单号与订单金额
// 筛选所有有效订单 并收集订单号 与 订单金额
Map<String,Double> map=ordersList.stream().filter((order) -> order.getIsValid() == 1).
collect(Collectors.toMap(Order::getOrderNo, Order::getTotal));
// java8 下对map进行遍历操作 如果 Map的Key重复,会报错
map.forEach((k,v)->{
System.out.println("k:"+k+":v:"+v);
});
十二、汇总


- 筛选所有有效订单 返回订单总数
System.out.println("count结果:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.counting())
);
System.out.println("count结果:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.count()
);
- 返回订单总金额
System.out.println("订单总金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.summarizingDouble(Order::getTotal))
);
System.out.println("订单总金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.mapToDouble(Order::getTotal)
.sum()
);
System.out.println("订单总金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.reduce(Double::sum)
.get()
);
- 返回用户id=20 有效订单平均每笔消费金额
System.out.println("用户id=20 有效订单平均每笔消费金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.filter((order -> order.getUserId()==20))
.collect(Collectors.averagingDouble(Order::getTotal))
);
System.out.println("用户id=20 有效订单平均每笔消费金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.filter((order -> order.getUserId()==20))
.mapToDouble(Order::getTotal)
.average()
.getAsDouble()
);
System.out.println("用户id=20 有效订单平均每笔消费金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.filter((order -> order.getUserId()==20))
.collect(Collectors.summarizingDouble(Order::getTotal))
.getAverage()
);
- 筛选所有有效订单 并计算订单总金额
System.out.println("订单总金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.summingDouble(Order::getTotal))
);
十三、最值
筛选所有有效订单 并计算最小订单金额
System.out.println("最小订单金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.collect(Collectors.minBy(Double::compare))
);
筛选所有有效订单 并计算最大订单金额
// 筛选所有有效订单 并计算最大订单金额
System.out.println("最大订单金额:"+
ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal)
.collect(Collectors.maxBy(Double::compare))
);
十四、分组&分区
14.1 分组
- 根据有效订单支付状态进行分组操作
Map<Integer,List<Order>> g01=ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.groupingBy(Order::getStatus));
g01.forEach((status,order)->{
System.out.println("----------------");
System.out.println("订单状态:"+status);
order.forEach(System.out::println);
});
- 筛选有效订单,根据用户id 和 支付状态进行分组
Map<Integer,Map<String,List<Order>>> g02= ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.groupingBy(Order::getUserId,
Collectors.groupingBy((o)->{
if(o.getStatus()==0){
return "未支付";
}else if (o.getStatus()==1){
return "已支付";
}else if (o.getStatus()==2){
return "待发货";
}else if (o.getStatus()==3){
return "已发货";
}else if (o.getStatus()==4){
return "已接收";
} else{
return "已完成";
}
}
))
);
g02.forEach((userId,m)->{
System.out.println("用户id:"+userId+"-->有效订单如下:");
m.forEach((status,os)->{
System.out.println("状态:"+status+"---订单列表如下:");
os.forEach(System.out::println);
});
System.out.println("-----------------------");
});
14.2 分区
- 分区操作-筛选订单金额>1000 的有效订单
Map<Boolean,List<Order>> g03= ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.collect(Collectors.partitioningBy((o)->o.getTotal()>1000));
g03.forEach((b,os)->{
System.out.println("分区结果:"+b+"--列表结果:");
os.forEach(System.out::println);
});
- 拼接操作-筛选有效订单并进行拼接
String orderStr=ordersList.stream()
.filter((order) -> order.getIsValid() == 1)
.map(Order::getOrderNo)
.collect(Collectors.joining(","));
System.out.println(orderStr);
十五、流的应用
乐字节-Java8核心特性实战之Stream(流)的更多相关文章
- 乐字节-Java8核心特性实战之Lambda表达式
大家好,小乐又来给大家分享Java8核心特性了,上一篇文章是<乐字节|Java8核心实战-接口默认方法>,这次就来讲Java8核心特征之Lambda表达式. Java8 引入Lambda表 ...
- 乐字节-Java8核心特性实战-接口默认方法
JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...
- 乐字节-Java8核心特性实战之函数式接口
什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一 ...
- 乐字节Java8核心特性之方法引用
大家好,我是乐字节的小乐,上一次我们说到了Java8核心特性之函数式接口,接下来我们继续了解Java8又一核心特性--方法引用. Java8 中引入方法引用新特性,用于简化应用对象方法的调用, 方法引 ...
- 乐字节Java8核心特性之Optional类
大家好啊,上次小乐给大家介绍了Java8最最重要的一个特性——Stream流,点击可以回顾哦. Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在 ...
- 乐字节-Java8新特性-接口默认方法
总概 JAVA8 已经发布很久,而且毫无疑问,java8是自java5(2004年发布)之后的最重要的版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性. Java8 新特性列表如下: 接 ...
- 乐字节-Java8新特性之Base64和重复注解与类型注解
上一篇小乐给大家说了<乐字节-Java8新特性之Date API>,接下来小乐继续给大家说一说Java8新特性之Base64和重复注解与类型注解. 一.Base64 在Java 8中,内置 ...
- 乐字节-Java8新特性-接口默认方法之Stream流(下)
接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 ...
- 乐字节-Java8新特性之Stream流(上)
上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...
随机推荐
- 解决webpack不能匹配post请求的问题
解决webpack不能匹配post请求的问题 webpack的dev-server只能匹配get请求,在本地做本地数据的时候会很不方便. 可以使用如下两种办法解决: 1.在webpack.config ...
- Android中m、mm、mmm、mma、mmma的区别
m:编译整个安卓系统 makes from the top of the tree mm:编译当前目录下的模块,当前目录下需要有Android.mk这个makefile文件,否则就往上找最近的Andr ...
- haproxysocket 参数记录
haproxy的一些指标 pxname 组名 svname 服务器名 qcur 当前队列 qmax 最大队列 scur当前会话用户 smax最大会话用户 slim会话限制 stot会话 ...
- js/html/css做一个简单的图片自动(auto)轮播效果//带注释
FF(firefox)/chrom/ie稳定暂无bug...注意:请自己建立一个images文件,放入几张900*238的图片(注意图片格式和名字与程序中一致). 1. [图片] 1.JPG 2. [ ...
- 分享知识-快乐自己:Struts2 - result标签的name属性和type属性
1):result的name属性 例如:<result name="success">/pages/success.jsp</result> Strut ...
- sass与compass实战(读书笔记)
// compass create myproject // compass compile // compass compile --force 重新编译未改动的 // compass compil ...
- Spring笔记01(基础知识)
1.基础知识 01.Spring:轻量级Java EE开源框架,它是由Rod Johnson为了解决企业应用程序开发的复杂性而创建. 02.目标:实现一个全方位的整合框架,实现“一站式”的企业应用开发 ...
- 系列文章-- SSIS学习
SSIS是SQL Server Integraion Services的简称.是生成高性能数据集成解决方案(包括数据仓库的提取.转换和加载 (ETL) 包)的平台. SSIS组件转换_模糊查找转换 ...
- BZOJ1146:[CTSC2008]网络管理
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...
- CF 504 E —— Misha and LCP on Tree —— 树剖+后缀数组
题目:http://codeforces.com/contest/504/problem/E 快速查询LCP,可以用后缀数组,但树上的字符串不是一个序列: 所以考虑转化成序列—— dfs 序! 普通的 ...