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 等

代码示例

数据准备

  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

原文地址:https://www.cnblogs.com/sanri1993/p/11580929.html

时间: 2024-08-01 13:41:44

Java8 Streams 让集合操作飞起来的相关文章

Java8 新特性之集合操作Stream

Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同. stream是对集合对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作,或者大批量数据操作. 为什么要使用Stream 函数式编程带来的好处尤为明显.这种代码更多地表达了业务逻辑的意图,而不是它的实现机制.易读的代码也易于维护.更可靠.更不容易出错. 高端 使用实例: 测试数据:

java中的集合操作类(未完待续)

申明: 实习生的肤浅理解,如发现有错误之处,还望大牛们多多指点 废话 其实我写java的后台操作,我每次都会遇到一条语句:List<XXXXX> list = new ArrayList<XXXXX>(); 但是我仅仅只是了解,list这个类是一个可变长用来存储的对象实例的类,我甚至觉得这个List对象可以理解成数组,但是却又与java中咱们正常理解的数组很多的不同,比如说,他的长度可以随着需要自动增长,比如说,实例化一个List类就和咱们声明数组的时候是不一样的! 今天的实习生活

orcale 之 集合操作

集合操作就是将两个或者多个 sql 查询的结果合并成复合查询.常见的集合操作有UNION(并运算).UNION ALL.INTERSECT(交运算)和MINUS(差运算). UNION UNION 运算可以将多个查询结果集相加,形成一个结果集, 其结果相当于集合运算的并运算. UNION 可以将第一个查询结果的所有行与第二个结果集的所有行进行相加,行切消除所有的重复行.语法如下: SELECT column1 [, column2 ] FROM table1 [, table2 ] [WHERE

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

set集合,是一个无序且不重复的元素集合.定义方式类似字典使用{}创建 目前我们学过的数据类型: 1.字符串(str),2.整型(int),3.浮点型(float),4,列表(list) 5.元组(tuple),6.字典(dict),7.集合(set),8.布尔型(bool) 1.集合创建 2.集合操作   2.1 set.add 添加元素 往set中添加一个元素只有set中不存在该元素时,才会加入该元素   2.2 set.clear 清空所有元素 从set中移除所有元素   2.3 set.

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

Unit05: 集合操作 -- 查找表 使用该类测试自定义元素的集合排序 package day05; /** * 使用该类测试自定义元素的集合排序 * @author adminitartor * */ public class Point implements Comparable<Point>{ private int x; private int y; public Point(int x, int y) { super(); this.x = x; this.y = y; } pub

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

Unit04: 集合框架 . 集合操作 -- 线性表 操作集合元素相关方法 package day04; import java.util.ArrayList; import java.util.Collection; import day02.Point; /** * 操作集合元素相关方法 * @author adminitartor * */ public class Collection_Remove { public static void main(String[] args) { C

集合操作

.MongoDB介绍(数据库是用来存数据的) - 特点  - mongodb是nosql(not only sql)数据库中的一种  - 以bson(binary json)文档方式存储数据 - 优点  - 高开发效率:   - 采用bson文档,避免了表(table)和对象(object)的映射   - 使用对象语法,js语法上手容易  - 高性能(查询性能):   - 内存映射:比磁盘io操作快   - 内嵌属性:避免了多表联查  - 高扩展   - 天生分布式数据库,易扩容   - 非结构

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

原文标题:Functional Android (II): Collection operations in Kotlin 原文链接:http://antonioleiva.com/collection-operations-kotlin/ 原文作者:Antonio Leiva(http://antonioleiva.com/about/) 原文发布:2015-09-29 在简化代码方面,Lambda表达式是一个杰出的工具,而且还可以完成之前不可能完成的事.我们在这个系列文章的第一篇(Unlea

Oracle集合操作函数:union、intersect、minus

[转]Oracle集合操作函数:union.intersect.minus 集合操作符专门用于合并多条select 语句的结果,包括:UNION, UNION ALL, INTERSECT, MINUS.当使用集合操作符时,必须确保不同查询的列个数和数据类型匹配. 集合操作符具有以下注意事项: 集合操作符不适用于LOB.VARRAY和嵌套表列. UNION.INTERSECT.MINUS操作符不使用于 LONG列. 如果选择列表中包含有表达式或者函数,那么必须为表达式或者函数定义列别名. 1.U