Java8 Streams 让集合操作飞起来
前言
接上篇文章 java8 新特性 由于上篇过于庞大,使得重点不够清晰,本篇单独拿出 java8 的 Stream 重点说明 ,并做了点补充。
基本说明
- Stream 是基于 java8 的 lambda 表达式的,如果不清楚 lambda 表达式,可以查看我的上篇文章Lambda 表达式和函数式接口快速理解
- Stream 把要处理的元素看做一种流,流在管道中传输,可以在管道的节点上处理数据,包含过滤,去重,排序,映射,聚合,分组等。
- Stream 分为中间操作和后期操作,中期操作会形成一个新的 Stream ,但不会马上对数据进行处理,到后期操作时,再遍历整个集合;可以没有中期操作直接后期操作。
创建流的方式
- 使用
java.util.Collection接口的默认方法stream或者parallelStream - 使用
java.util.Arrays的方法stream将数组变成流
中期操作和后期操作
Stream 分为中间操作和后期操作,中期操作会形成一个新的 Stream ,但不会马上对数据进行处理,到后期操作时,再遍历整个集合;可以没有中期操作直接后期操作。
中期操作
- map 和 map 之类的,用于映射一种类型到另一种类型
- filter 用于过滤掉一些不符合要求的元素
- distinct 用于排重
- sorted 用于排序
- flatMap 用于将流扁平化
后期操作
forEach,collect,reduce,anyMatch,allMatch,noneMatch,findFirst 等;
其中属 collect 最为常用,还有一个专门用于 collect 的 Collectors 类,可以用于将集合转成 List,Set,Map 等
代码示例
数据准备
- 准备一个用于下面例子测试的对象
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Vehicle {
//车架号
private String vin;
// 车主手机号
private String phone;
// 车主姓名
private String name;
// 所属车租车公司
private Integer companyId;
// 个人评分
private Double score;
//安装的设备列表imei,使用逗号分隔
private String deviceNos;
}
- 准备一些车辆数据
static List<Vehicle> vehicles = new ArrayList<>();
@Before
public void init(){
List<String> imeis = new ArrayList<>();
for (int i = 0; i <5 ; i++) {
List<String> singleVehicleDevices = new ArrayList<>();
for (int j = 0; j < 3; j++) {
String imei = RandomStringUtils.randomAlphanumeric(15);
singleVehicleDevices.add(imei);
}
imeis.add(StringUtils.join(singleVehicleDevices,','));
}
vehicles.add(new Vehicle("KPTSOA1K67P081452","17620411498","9420",1,4.5,imeis.get(0)));
vehicles.add(new Vehicle("KPTCOB1K18P057071","15073030945","张玲",2,1.4,imeis.get(1)));
vehicles.add(new Vehicle("KPTS0A1K87P080237","19645871598","sanri1993",1,3.0,imeis.get(2)));
vehicles.add(new Vehicle("KNAJC526975740490","15879146974","李种",1,3.9,imeis.get(3)));
vehicles.add(new Vehicle("KNAJC521395884849","13520184976","袁绍",2,4.9,imeis.get(4)));
}
forEach 遍历Collection 数据
vehicles.forEach(vehicle -> System.out.println(vehicle));
//这样就可以遍历打印
vehicles.forEach(System.out::println);
forEach 遍历 Map 数据
Map<String,Integer> map = new HashMap<>();
map.put("a",1);map.put("b",2);map.put("c",3);
map.forEach((k,v) -> System.out.println("key:"+k+",value:"+v));
filter 数据过滤
// 去掉评分为 3 分以下的车
List<Vehicle> collect = vehicles.stream().filter(vehicle -> vehicle.getScore() >= 3).collect(Collectors.toList());
map 对象映射
对一个 List<Object> 大部分情况下,我们只需要列表中的某一列,或者需要把里面的每一个对象转换成其它的对象,这时候可以使用 map 映射,示例:
// 取出所有的车架号列表
List<String> vins = vehicles.stream().map(Vehicle::getVin).collect(Collectors.toList());
groupBy 按照某个属性进行分组
// 按照公司 Id 进行分组
Map<Integer, List<Vehicle>> companyVehicles = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId));
// 按照公司分组求司机打分和
Map<Integer, Double> collect = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId, Collectors.summingDouble(Vehicle::getScore)));
sort 按照某个属性排序 ,及多列排序
// 单列排序
vehicles.sort((v1,v2) -> v2.getScore().compareTo(v1.getScore()));
// 或使用 Comparator 类来构建比较器,流处理不会改变原列表,需要接收返回值才能得到预期结果
List<Vehicle> collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()).collect(Collectors.toList());
// 多列排序,score 降序,companyId 升序排列
List<Vehicle> collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()
.thenComparing(Comparator.comparing(Vehicle::getCompanyId)))
.collect(Collectors.toList());
flatMap 扁平化数据处理
// 查出所有车绑定的所有设备
List<String> collect = vehicles.stream().map(vehicle -> {
String deviceNos = vehicle.getDeviceNos();
return StringUtils.split(deviceNos,',');
}).flatMap(Arrays::stream).collect(Collectors.toList());
flatMap 很适合 List<List> 或 List<object []> 这种结构,可以当成一个列表来处理;像上面的设备列表,在数据库中存储的结构就是以逗号分隔的数据,而车辆列表又是一个列表数据。
将 List 数据转成 Map
// 将 List 转成 Map ; key(vin) == > Vehicle
Map<String, Vehicle> vinVehicles = vehicles.stream().collect(Collectors.toMap(Vehicle::getVin, vehicle -> vehicle));
mapReduce 数据处理
// 对所有司机的总分求和
Double reduce = vehicles.stream().parallel().map(Vehicle::getScore).reduce(0d, Double::sum);
求百分比
// 总的分值
Double totalScore = vehicles.stream().parallel().map(Vehicle::getScore).reduce(0d, Double::sum);
// 查看每一个司机占的分值比重
List<String> collect = vehicles.stream()
.mapToDouble(vehicle -> vehicle.getScore() / totalScore)
.mapToLong(weight -> (long) (weight * 100))
.mapToObj(percentage -> percentage + "%")
.collect(Collectors.toList());
anyMatch/allMatch/noneMatch 匹配操作
- anyMatch 只要有元素匹配,即返回真
- allMatch 要求所有的元素都匹配
- noneMatch 要求没有一个元素匹配
// 检查是否有姓李的司机 true
boolean anyMatch = vehicles.stream().anyMatch(vehicle -> vehicle.getName().startsWith("李"));
// 检查是否所有司机的评分都大于 3 分 false
boolean allMatch = vehicles.stream().allMatch(vehicle -> vehicle.getScore() > 3);
// 检查是否有 3 公司的特务 true
boolean noneMatch = vehicles.stream().noneMatch(vehicle -> vehicle.getCompanyId() == 3);
一点小推广
创作不易,希望可以支持下我的开源软件,及我的小工具,欢迎来 gitee 点星,fork ,提 bug 。
Excel 通用导入导出,支持 Excel 公式
博客地址:https://blog.csdn.net/sanri1993/article/details/100601578
gitee:https://gitee.com/sanri/sanri-excel-poi
使用模板代码 ,从数据库生成代码 ,及一些项目中经常可以用到的小工具
博客地址:https://blog.csdn.net/sanri1993/article/details/98664034
gitee:https://gitee.com/sanri/sanri-tools-maven
Java8 Streams 让集合操作飞起来的更多相关文章
- Java8 新特性之集合操作Stream
Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...
- 函数式Android编程(II):Kotlin语言的集合操作
原文标题:Functional Android (II): Collection operations in Kotlin 原文链接:http://antonioleiva.com/collectio ...
- JAVASE02-Unit05: 集合操作 —— 查找表
Unit05: 集合操作 -- 查找表 使用该类测试自定义元素的集合排序 package day05; /** * 使用该类测试自定义元素的集合排序 * @author adminitartor * ...
- JAVASE02-Unit04: 集合框架 、 集合操作 —— 线性表
Unit04: 集合框架 . 集合操作 -- 线性表 操作集合元素相关方法 package day04; import java.util.ArrayList; import java.util.Co ...
- oracle之集合操作函数---minus、union、intersect
集合操作符专门用于合并多条select语句的结果,包括:UNION,UNION ALL,INTERSECT,MINUS.当使用集合操作函数时,需保证数据集的字段数据类型和数目一致. 使用集合操作符需要 ...
- Scala集合操作
大数据技术是数据的集合以及对数据集合的操作技术的统称,具体来说: 1.数据集合:会涉及数据的搜集.存储等,搜集会有很多技术,存储技术现在比较经典方案是使用Hadoop,不过也很多方案采用Kafka. ...
- Python 集合set添加删除、交集、并集、集合操作符号
在Python中集合set是基本数据类型的一种,它有可变集合(set)和不可变集合(frozenset)两种.创建集合set.集合set添加.集合删除.交集.并集.差集的操作都是非常实用的方法. 1. ...
- Python 集合操作
1.集合操作 集合是一个无序的,不重复的数据组合, 他的主要作业如下. 1.去重,把一个列表变成集合,就自动去重了 2.关系测试,测试两组数据之前的交集.差集.并集等关系 list_1 = [1,4, ...
- Python学习笔记-Day3-set集合操作
set集合,是一个无序且不重复的元素集合.定义方式类似字典使用{}创建 目前我们学过的数据类型: 1.字符串(str),2.整型(int),3.浮点型(float),4,列表(list) 5.元组(t ...
随机推荐
- Python自动化开发
阅读目录 第一篇:python入门 第二篇:字符编码.文件处理 第三篇:函数 第四篇:迭代器.生成器.三元表达式.列表生成式 第五篇:模块.包.软件开发规范 第六篇:日志模块 第七篇:常用模块 第八篇 ...
- Zabbix数据库空间大小使用计算
一.Zabbix的数据存储主要分类 1.历史数据 2.趋势数据 3.事件数据 二.每秒处理的数据量 顾名思义,例如,有3000个监控项(item),每60秒取一次值,即平均每秒有50(3000/60) ...
- xpath中normalize-space的用法【转载】
下面这个菜单中,要点击“货运表现”,我们来看一下xpath, 菜单中的所有项的id都是“vertab”,所以不能用id来定位,那么先用文本的xpath试试 //a[text()='货运表现'] 发现定 ...
- Appium+Python API相关知识了解
首先,要先了解,官方Appium API // https://testerhome.com/topics/3144 刚开始的时候,没有看官方API,然后在网上瞎找学习资料,发现python相关的很少 ...
- Filter(过滤器)(有待补充)
Filter(过滤器) 一.Filter(过滤器)简介 Filter 的基本功能是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊的 ...
- python2和python3的解释器安装
python环境及安装 主板:人的骨架 用于扩展设备 CPU:人的大脑 用于计算和逻辑处理 硬板:肚子 存储数据(永久存储) C盘···· 内存:存储数据(临时储存) 没有保存会消失 电源:人的心脏 ...
- 基于JRebel开发的MySQL Explain插件
前言 我们在使用数据库时,为了使业务系统性能达到最优,往往都需要避免慢SQL查询,不能等到线上告警了再排查是否为慢SQL导致.在开发阶段,每个开发人员就应该针对自己写的SQL看是否可能为慢SQL,从而 ...
- netty源码解解析(4.0)-20 ChannelHandler: 自己实现一个自定义协议的服务器和客户端
本章不会直接分析Netty源码,而是通过使用Netty的能力实现一个自定义协议的服务器和客户端.通过这样的实践,可以更深刻地理解Netty的相关代码,同时可以了解,在设计实现自定义协议的过程中需要解决 ...
- 听说你不会调参?TextCNN的优化经验Tricks汇总
前言:本篇是TextCNN系列的第三篇,分享TextCNN的优化经验 前两篇可见: 文本分类算法TextCNN原理详解(一) TextCNN代码详解(附测试数据集以及GitHub 地址)(二) 调优模 ...
- 线段树模板 hdu 1166 敌兵布阵
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...