乐字节-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中对于 ...
随机推荐
- touchweb手机网站图片加载方法(canvas加载和延迟加载)
一.canvas图片加载 关于canvas加载,我的方法是,将文章中所有用到图片的地方,都用canvas代替,给canvas一个data-src,里面存放img的路径,通过canvas方法渲染图片.因 ...
- HTML5_CSS3仿Google Play垂直菜单
在线演示 本地下载
- ubuntu mysql 配置(远程访问&&字符集设置&&忽略大小写)
1.安装 参考http://www.cnblogs.com/wuhou/archive/2008/09/28/1301071.html sudo apt-get install mysql-serve ...
- Spring Boot2.0之@Async实现异步调用
补充一个知识点: lombok底层原理使用的是: 字节码技术ASM修改字节码文件,生成比如类似于get() set( )方法 一定要在开发工具安装 在编译时候修改字节码文件(底层使用字节码技术),线上 ...
- ES6 Map数据结构
Map JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键.这给它的使用带来了很大的限制. ES6 提供了 Map 数据结构.它类似于对 ...
- NO1:在Windows端安装SecureCRT来连接Linux
正常情况下都不会直接在Linux服务端进行操作,实际使用服务器和工作电脑不会在同一个地方,也不允许在服务器操作. 我这里用SecureCRT 7.0来连接服务器.提供个下载,带注册机工具: http: ...
- 相对路径转绝对路径C++实现
#include<iostream> #include<string> #include<vector> using namespace std; //相对路径转绝 ...
- Mesos以及Marathon安装总结
安装了将近一周的环境了,终于把Mesos以及Marathon给安装上了,我指的离线安装. 策略1: 严格的按照官网的流程: http://mesos.apache.org/gettingstarted ...
- HL7 Event Type
Table 0003 - Event type Value Description A01 ADT/ACK - Admit / visit notification A02 ADT/ACK - Tra ...
- Ubuntu——查看内存和CPU情况
查看内存及cpu使用情况的命令:top 也可以安装htop工具,这样更直观,安装命令如下:sudo apt-get install htop安装完后,直接输入命令:htop