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 vehicles = new ArrayList<>();

@Before
public void init(){
    List imeis = new ArrayList<>();
    for (int i = 0; i <5 ; i  ) {
        List 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 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 collect = vehicles.stream().filter(vehicle -> vehicle.getScore() >= 3).collect(Collectors.toList());

map 对象映射

对一个 List 大部分情况下,我们只需要列表中的某一列,或者需要把里面的每一个对象转换成其它的对象,这时候可以使用 map 映射,示例:

// 取出所有的车架号列表
 List vins = vehicles.stream().map(Vehicle::getVin).collect(Collectors.toList());

groupBy 按照某个属性进行分组

// 按照公司 Id 进行分组
Map> companyVehicles = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId));

// 按照公司分组求司机打分和
Map collect = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId, Collectors.summingDouble(Vehicle::getScore)));

sort 按照某个属性排序 ,及多列排序

// 单列排序 
vehicles.sort((v1,v2) -> v2.getScore().compareTo(v1.getScore()));

// 或使用 Comparator 类来构建比较器,流处理不会改变原列表,需要接收返回值才能得到预期结果
 List collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()).collect(Collectors.toList());

// 多列排序,score 降序,companyId 升序排列
List collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()
                .thenComparing(Comparator.comparing(Vehicle::getCompanyId)))
                .collect(Collectors.toList());

flatMap 扁平化数据处理

// 查出所有车绑定的所有设备
List collect = vehicles.stream().map(vehicle -> {
    String deviceNos = vehicle.getDeviceNos();
    return StringUtils.split(deviceNos,',');
}).flatMap(Arrays::stream).collect(Collectors.toList());

flatMap 很适合 List List 这种结构,可以当成一个列表来处理;像上面的设备列表,在数据库中存储的结构就是以逗号分隔的数据,而车辆列表又是一个列表数据。

将 List 数据转成 Map

// 将 List 转成 Map ; key(vin) == > Vehicle
Map 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 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/100601578gitee:https://gitee.com/sanri/sanri-excel-poi

使用模板代码 ,从数据库生成代码 ,及一些项目中经常可以用到的小工具博客地址:https://blog.csdn.net/sanri1993/article/details/98664034gitee:https://gitee.com/sanri/sanri-tools-maven

展开阅读全文
  • 点赞
  • 评论
  • 分享
    x

    海报分享

    扫一扫,分享海报

  • 收藏
  • 手机看

    分享到微信朋友圈

    x

    扫一扫,手机阅读

    • 打赏
    • 文章举报

    打赏

    $9420

    “觉得好就赏点小费吧,^_^”

    5C币 10C币 20C币 50C币 100C币 200C币

    确定

  • 关注
收起全文

9420 技术博客

09-22 5093

java8 新特性精心整理(全)

前言越来越多的项目已经使用 Java 8 了,毫无疑问, Java 8JavaJava 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和 JVM 等方面的十多个新特性。在本文中我们将学习这些新特性,并用实际的例子说明在什么场景下适合使用。引用:本文参考了这两篇文章,加以自己的理解,整理成一份最容易理解的 Java 8 新特性文章,有少部分章节可能内容一致,但绝对......
还能输入1000个字符

java Stream的Collectors.toMap是怎么用的?

02-28

卜可的博客

11-22 3万+

java8stream操作:从集合中获取符合条件的元素

List<Student> students = new ArrayList<>(); students.add(new Student(1,"张三",90)); students.add(new Student(2,"李四",60)); students.add(new Student(3,"王五",30)); ...

WXF_Sir的博客

08-24 185

java8的Stream对集合操作

简介 java 8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到 集合,遍历 集合可以试下lambda表达式,经常还要对 集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。Stream作为 java 8的新特性,基于lambda表达式,是对 集合对象功能的增强,它专注于对 集合对象进行各种高效、便利的聚合操......

XuJiangDong

08-28 64

巧用Java8中的Stream,让集合操作起来

简介 java 8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到 集合,遍历 集合可以试下lambda表达式,经常还要对 集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。Stream作为 java 8的新特性,基于lambda表达式,是对 集合对象功能的增强,它专注于对 集合对象进行各种高效、便利的聚合 操作......

不忘初心

04-21 1194

面试官问我Java8~14的有哪些重要的新特性,我哭了~~~

大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成。 Java 8新特性见这里: Java 8新特性最佳指南 。Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实! Java9发布于 2017 年 9 月 21 日 。作为 Java 8 之后 3 年半才发布的新版本, Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模......

哎幽的成长

09-11 2500

java 8 部分新特性和函数式编程

1.接口可以添加非抽象的方法,使用关键字 default 即可 代码如下:public interface I java 8 { void getName(String name); default String getName2(String name){ return name; }}实现如下:public class Java 8 implements Ija

Java成神之路

04-13 1056

Java编程思想第五版(On Java8)(二十四)-并发编程

文章目录第二十四章 并发编程术语问题并发的新定义并发的超能力并发为速度而生四句格言1.不要这样做2.没有什么是真的,一切可能都有问题3.它起作用,并不意味着它没有问题4.你必须仍然理解残酷的真相本章其余部分并行流创建和运行任务终止耗时任务CompletableFuture类基本用法结合CompletableFutures模拟例外情况流异常检查异常死锁构造函数非线程安全复杂性和代价本章小结缺点共享内......

戴璟昊的博客

12-07 5626

【工作笔记】java1.8新特性之stream初使用:list分组、实体转换、求和

jdk1. 8新特性 stream初使用

Kevan的博客

05-11 2万+

Java8 Stream 分组求和使用笔记

Java 8Stream分组求和使用笔记话不多说,直接贴代码publicstaticvoidmain(String[]args){Foofoo1=newFoo(1,2);Foofoo2=newFoo(2,23);Foofoo3=newFoo(2,6);List&amp;lt;Foo...

weixin_33982670的博客

04-01 899

Java 8 特性—— Streams 构造树结构

2019独角兽企业重金招聘Python工程师标准>>> ...

三思而后行

05-16 92

《给大忙人看的java8》摘抄

函数式接口:只包含一个抽象方法的接口lambda表达式:是一段可以传递的代码   你最好将一个lambda表达式想象成一个函数,而不是一个对象,并记住它可以被转换为一个函数式接口。事实上,函数式接口的转换是你在 Java中使用lambda表达式能做的唯一一件事。 方法引用:又是要传递给其他代码的 操作已经有实现的方法了,这时可以使用“方法引用”,等同于lambda表......

程序员欧阳思海

09-28 3513

Java11正式发布了,我们该怎么办?

主题互动 Java11已经发布了,我们今天聊聊大家还停留在哪个版本呢?大家对于新版本的迅速的发布有什么想说的呢?09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本。我们都知道,前面的几个版本都不是长期支持的,然而,现在发布这个最新的长期支持的版本还是非常有意义的。 Java11也有许多的地方增加了新的功能,当然,也有一些功能删除了。下面......

旋转跳跃后空翻中的阿喵 - 热爱,专注,精益求精

08-30 2万+

JAVA各版本特性】JAVA 1.0 - JAVA 13

闲来想了解下各版本之间的特性,搜索没有最新的特性说明,故想写一份。废话不多说。JDKVersion1.01996-01-23Oak(橡树)初代版本,伟大的一个里程碑,但是是纯解释运行,使用外挂JIT,性能比较差,运行速度慢。JDKVersion1.11997-02-19JDBC( JavaDataBaseConnectivity); 支持内部类; RM......

Gane_Cheng的博客

07-09 1万+

Java的前世今生

Java 6年了,一直想对 Java有一个系统的认识,今天终于做了这件事。 Java不仅仅是一门编程语言,还是一个由一系列计算机软件和规范形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境,并广泛应用于嵌入式系统、移动终端、企业服务器、大型机等各种场合。时至今日, Java技术体系已经吸引了900多万软件开发者,这是全球最大的软件开发团队。使用 Java的设备多达几十亿台,其中包括11亿多台个人计算...

渴望变强

03-20 437

JAVA各版本的特性总结 (持续更新)

java12 (2019-03-19)1. 低暂停时间的GC;2. 微基准测试套件;3. Switch表达式;4. JVM常量API;5. 只保留一个AArch64实现;6. 默认类数据共享归档文件;7. 可终止的G1 Mixed GC; 8. G1及时返回未使用的已分配内存; java11 (201 8-09-25)1. 1 81:Nest-Based访问控制;2. 309:动态......

李人

09-26 1673

JAVA的各版本新特性】JAVA 5.0 - JAVA 11

JAVA 52004-09-30 Tiger(老虎)泛型; 增强循环,可以使用迭代方式; 自动装箱与自动拆箱; 类型安全的枚举; 可变参数; 静态引入; 元数据(注解); Instrumentation; JAVA 62006-12-11 Mustang(野马)支持脚本语言; JDBC 4.0API; Java Compiler API; 可插拔注解; 增加对......

LaoJiuJun的博客

08-05 98

Java各版本特性一览-从Java1.0到Java12

JDK Version 1.01996-01-23 Oak(橡树)初代版本,伟大的一个里程碑,但是是纯解释运行,使用外挂JIT,性能比较差,运行速度慢。JDK Version 1.11997-02-19– JDBC( Java DataBase Connectivity);– 支持内部类;– RMI(Remote Method Invocation) ;– 反射;– Java Be......
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
应支付 0元
点击重新获取
扫码支付

支付成功即可阅读

你可能感兴趣的:(java,java,spring,bash)