前言

接上篇文章 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 等

代码示例

数据准备

  1. 准备一个用于下面例子测试的对象
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;
}
  1. 准备一些车辆数据
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 让集合操作飞起来的更多相关文章

  1. Java8 新特性之集合操作Stream

    Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...

  2. 函数式Android编程(II):Kotlin语言的集合操作

    原文标题:Functional Android (II): Collection operations in Kotlin 原文链接:http://antonioleiva.com/collectio ...

  3. JAVASE02-Unit05: 集合操作 —— 查找表

    Unit05: 集合操作 -- 查找表 使用该类测试自定义元素的集合排序 package day05; /** * 使用该类测试自定义元素的集合排序 * @author adminitartor * ...

  4. JAVASE02-Unit04: 集合框架 、 集合操作 —— 线性表

    Unit04: 集合框架 . 集合操作 -- 线性表 操作集合元素相关方法 package day04; import java.util.ArrayList; import java.util.Co ...

  5. oracle之集合操作函数---minus、union、intersect

    集合操作符专门用于合并多条select语句的结果,包括:UNION,UNION ALL,INTERSECT,MINUS.当使用集合操作函数时,需保证数据集的字段数据类型和数目一致. 使用集合操作符需要 ...

  6. Scala集合操作

    大数据技术是数据的集合以及对数据集合的操作技术的统称,具体来说: 1.数据集合:会涉及数据的搜集.存储等,搜集会有很多技术,存储技术现在比较经典方案是使用Hadoop,不过也很多方案采用Kafka.  ...

  7. Python 集合set添加删除、交集、并集、集合操作符号

    在Python中集合set是基本数据类型的一种,它有可变集合(set)和不可变集合(frozenset)两种.创建集合set.集合set添加.集合删除.交集.并集.差集的操作都是非常实用的方法. 1. ...

  8. Python 集合操作

    1.集合操作 集合是一个无序的,不重复的数据组合, 他的主要作业如下. 1.去重,把一个列表变成集合,就自动去重了 2.关系测试,测试两组数据之前的交集.差集.并集等关系 list_1 = [1,4, ...

  9. Python学习笔记-Day3-set集合操作

    set集合,是一个无序且不重复的元素集合.定义方式类似字典使用{}创建 目前我们学过的数据类型: 1.字符串(str),2.整型(int),3.浮点型(float),4,列表(list) 5.元组(t ...

随机推荐

  1. CZGL.Auth: ASP.NET Core Jwt角色授权快速配置库

    CZGL.Auth CZGL.Auth 是一个基于 Jwt 实现的快速角色授权库,ASP.Net Core 的 Identity 默认的授权是 Cookie.而 Jwt 授权只提供了基础实现和接口,需 ...

  2. java 程序执行顺序之继承

    1.首先会初始化父类,因为没有父类子类也无从谈起.第一步初始化static 变量 或者 静态初始化话块 2.初始化子类的static 变量 或者 静态初始化块 3.顺序初始化父类普通变量 或者 父类普 ...

  3. urllib.request.urlretrieve()用于下载制定url内容到本地

    函数:urllib.urlretrieve(url[, filename[, reporthook[, data]]]) 参数说明: url:外部或者本地url ,url中不要含有中文,好像会出错.f ...

  4. 16.XML语法、CDATA、约束(DTD、Schema)讲解

    xml主要用来描述数据,比如配置文件,网络之间传输数据等,并且在android中也经常用xml来布局,,接下来便来学习xml常用的东西 1.XML语法 xml语法分为: 1.1 文档声明 必须位于文档 ...

  5. 如何编写高质量的 JS 函数(1) -- 敲山震虎篇

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ作者:杨昆 一千个读者,有一千个哈姆雷特. 此系列文 ...

  6. vue项目中引入Sass

    Sass作为目前成熟,稳定,强大的css扩展语言,让越来越多的前端工程师喜欢上它.下面介绍了如何在vue项目 中引入Sass. 首先在项目文件夹执行命令 npm install vue-cli -g, ...

  7. Docker搭建Zookeeper&Kafka集群

    最近在学习Kafka,准备测试集群状态的时候感觉无论是开三台虚拟机或者在一台虚拟机开辟三个不同的端口号都太麻烦了(嗯..主要是懒). 环境准备 一台可以上网且有CentOS7虚拟机的电脑 为什么使用虚 ...

  8. 随笔编号-04 AngularJS 相关小问题解决方案合集

    1  解决 Select选择框遍历时,出现一个空白选项: <select style="width: 20%;margin-left: 5px;height: 31px;" ...

  9. Markdown表格宽度调整

    Markdown 表格默认宽度是根据内容来的,如果某一列内容很长的话会将其他列的宽度占用导致显示样式很丑.我们可以在表格前增加 CSS 样式来限制列的宽度: <style> table t ...

  10. CentOS -- RocketMQ 4.3.2 standalone Installation and Configuration

    1 Download RockeMQ Package: You need to download it and put it to the OS Image. wget http://apache.c ...