Java8 stream处理List,Map总结

news/2024/4/26 6:39:02/文章来源:https://blog.csdn.net/y19910825/article/details/128107210

Java 8 Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • <strong元素队列< strong="">元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

生成流

在 Java 8 中, 集合接口有两个方法来生成流:

  • stream() − 为集合创建串行流。

  • parallelStream() − 为集合创建并行流

 下面写一下,我们经常会用到的一些操作案例

一,排序

   List     1, 对象集合排序//降序,根据创建时间降序;List<User> descList = attributeList.stream().sorted(Comparator.comparing(User::getCreateTime, Comparator.nullsLast(Date::compareTo)).reversed()).collect(Collectors.toList());//升序,根据创建时间升序;List<User> ascList = attributeList.stream().sorted(Comparator.comparing(User::getCreateTime, Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());2, 数字排序List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);//升序List<Integer> ascList = numbers.stream().sorted().collect(Collectors.toList());结果: [2, 2, 3, 3, 3, 5, 7]//倒序List<Integer> descList = numbers.stream().sorted((x, y) -> y - x).collect(Collectors.toList());结果:[7, 5, 3, 3, 3, 2, 2]3, 字符串排序List<String> strList = Arrays.asList("a", "ba", "bb", "abc", "cbb", "bba", "cab");//自然排序List<String> ascList = strList.stream().sorted().collect(Collectors.toList());结果:[a, abc, ba, bb, bba, cab, cbb]//反转,倒序ascList.sort(Collections.reverseOrder());结果:[cbb, cab, bba, bb, ba, abc, a]//直接反转集合Collections.reverse(strList);结果:[cab, bba, cbb, abc, bb, ba, a]Map//HashMap是无序的,当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了,排序后可以再转成HashMap。//LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的。//LinkedHashMap是线程不安全的。Map<String,String> map = new HashMap<>();map.put("a","123");map.put("b","456");map.put("z","789");map.put("c","234");//map根据value正序排序LinkedHashMap<String, String> linkedMap1 = new LinkedHashMap<>();map.entrySet().stream().sorted(Comparator.comparing(e -> e.getValue())).forEach(x -> linkedMap1.put(x.getKey(), x.getValue()));结果:{a=123, c=234, b=456, z=789}//map根据value倒序排序LinkedHashMap<String, String> linkedMap2 = new LinkedHashMap<>();map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).forEach(x -> linkedMap2.put(x.getKey(), x.getValue()));结果:{z=789, b=456, c=234, a=123}//map根据key正序排序LinkedHashMap<String, String> linkedMap3 = new LinkedHashMap<>();map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey())).forEach(x -> linkedMap3.put(x.getKey(), x.getValue()));结果:{a=123, b=456, c=234, z=789}//map根据key倒序排序LinkedHashMap<String, String> linkedMap4 = new LinkedHashMap<>();map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByKey())).forEach(x -> linkedMap4.put(x.getKey(), x.getValue()));结果:{z=789, c=234, b=456, a=123}

二,List 转 Map

     1、指定key-value,value是对象中的某个属性值。Map<Integer,String> userMap1 = userList.stream().collect(Collectors.toMap(User::getId,User::getName));2、指定key-value,value是对象本身,User->User 是一个返回本身的lambda表达式Map<Integer,User> userMap2 = userList.stream().collect(Collectors.toMap(User::getId,User->User));3、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身Map<Integer,User> userMap3 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));4、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身,key 冲突的解决办法,这里选择第二个key覆盖第一个key。Map<Integer,User> userMap4 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(),(key1,key2)->key2));5、将List根据某个属性进行分组,放入Map;然后组装成key-value格式的数据,分组后集合的顺序会被改变,所以事先设置下排序,然后再排序,保证数据顺序不变。List<GoodsInfoOut> lst = goodsInfoMapper.getGoodsList();Map<String, List<GoodsInfoOut>> groupMap = lst.stream().collect(Collectors.groupingBy(GoodsInfoOut::getClassificationOperationId));List<HomeGoodsInfoOut> retList = groupMap.keySet().stream().map(key -> {HomeGoodsInfoOut mallOut = new HomeGoodsInfoOut();mallOut.setClassificationOperationId(key);if(groupMap.get(key)!=null && groupMap.get(key).size()>0) {mallOut.setClassificationName(groupMap.get(key).get(0).getClassificationName());mallOut.setClassificationPic(groupMap.get(key).get(0).getClassificationPic());mallOut.setClassificationSort(groupMap.get(key).get(0).getClassificationSort());}mallOut.setGoodsInfoList(groupMap.get(key));return mallOut;}).collect(Collectors.toList());List<HomeGoodsInfoOut> homeGoodsInfoOutList = retList.stream().sorted(Comparator.comparing(HomeGoodsInfoOut::getClassificationSort)).collect(Collectors.toList());
       5、根据用户性别将数据 - 分组
     Map<String, List<UserInfo>> groupMap = userList.stream().collect(Collectors.groupingBy(UserInfo::getSex()));
       6、List实体转Map,想要有序的话,就使用以下操作(TreeMap 有序;Map 无序)
     TreeMap<String, List<BillPollEntity>> ascMonthBillPollMap = s.stream().collect(Collectors.groupingBy(t -> t.getDrawTime()), TreeMap::new, Collectors.toList()));
     //倒叙MAPNavigableMap<String, List<OpenActivityOut>> descMonthBillPollMap = ascMonthBillPollMap.descendingMap();
     Map<String, List<BillPollEntity>> monthBillPollMap = s.stream().collect(Collectors.groupingBy(BillPollEntity::getDrawTime));

 
 

三,Map 转 List

     Map<String,String> map1 = new HashMap<>();map1.put("a","123");map1.put("b","456");map1.put("z","789");map1.put("c","234");1、默认顺序List<UserInfo> list0 = map1.entrySet().stream().map(e -> new UserInfo(e.getValue(), e.getKey())).collect(Collectors.toList());结果:[UserInfo(userName=123, mobile=a), UserInfo(userName=456, mobile=b), UserInfo(userName=234, mobile=c), UserInfo(userName=789, mobile=z)]2、根据Key排序List<UserInfo> list1 = map1.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey())).map(e -> new UserInfo(e.getKey(), e.getValue())).collect(Collectors.toList());结果:[UserInfo(userName=a, mobile=123), UserInfo(userName=b, mobile=456), UserInfo(userName=c, mobile=234), UserInfo(userName=z, mobile=789)]3、根据Value排序List<UserInfo> list2 = map1.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).map(e -> new UserInfo(e.getKey(), e.getValue())).collect(Collectors.toList());结果:[UserInfo(userName=a, mobile=123), UserInfo(userName=c, mobile=234), UserInfo(userName=b, mobile=456), UserInfo(userName=z, mobile=789)]3、根据Key排序List<UserInfo> list3 = map1.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> new UserInfo(e.getKey(), e.getValue())).collect(Collectors.toList());结果:[UserInfo(userName=a, mobile=123), UserInfo(userName=b, mobile=456), UserInfo(userName=c, mobile=234), UserInfo(userName=z, mobile=789)]4、Map<String,UserInfo> 转 List<String>、List<UserInfo>// 取Map中的所有value结果:List<UserInfo> userInfoList = retMap.values().stream().collect(Collectors.toList());// 取Map中所有key结果:List<String> strList = retMap.keySet().stream().collect(Collectors.toList());
 

四,从List中获取某个属性

//拿出所有手机号
List<String> mobileList = userList.stream().map(RemindUserOut::getMobile).collect(Collectors.toList());
//拿出所有AppId,并去重
List<String> appIdList = appIdList.stream().map(WechatWebViewDomain::getAppId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
//拿出集合中重复的billNo,【.filter(map->StringUtils.isNotEmpty(map.getBillNo()))】这是过滤掉为空的数据;否则,有空数据会抛异常
List<String> repeatCodeList = resultList.stream().filter(map->StringUtils.isNotEmpty(map.getBillNo())).collect(Collectors.groupingBy(BillUploadIn::getBillNo, Collectors.counting())).entrySet().stream().filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());//拿出集合中几个属性拼接后的字符串
List<String> strList = myList.stream().map(p -> p.getName() + "-" + p.getMobile()).collect(Collectors.toList());

五,筛选并根据属性去重

List<UserInfo> uList = new ArrayList<>();
UserInfo u1 = new UserInfo(1,"小白","15600000000");
UserInfo u2 = new UserInfo(2,"小黑","15500000000");
uList.add(u1);
uList.add(u2);//过滤名字是小白的数据
List list1= uList.stream()
.filter(b -> "小白".equals(b.getUserName()))
.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(b -> b.getId()))), ArrayList::new));
结果:list1===[UserInfo(id=1, userName=小白, mobile=15600000000)]//根据ID去重
List list2= uList.stream()
.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(b -> b.getId()))), ArrayList::new));
结果:list2===[UserInfo(id=1, userName=小白, mobile=15600000000), UserInfo(id=2, userName=小黑, mobile=15500000000)]

  //整个数据去重
  list = list.stream().distinct().collect(Collectors.toList());

 

六,计算;和,最大,最小,平均值。

List<UserInfo> uList = new ArrayList<>();
UserInfo user1 = new UserInfo(1,"小白","15600000000",10,new BigDecimal(10));
UserInfo user2 = new UserInfo(2,"小黑","15500000000",15,new BigDecimal(20));
UserInfo user3 = new UserInfo(2,"小彩","15500000000",88,new BigDecimal(99));
uList.add(user1);
uList.add(user2);
uList.add(user3);//和
Double d1 = uList.stream().mapToDouble(UserInfo::getNum).sum();
结果:113.0
//最大
Double d2 = uList.stream().mapToDouble(UserInfo::getNum).max().getAsDouble();
结果:88.0
//最小
Double d3 = uList.stream().mapToDouble(UserInfo::getNum).min().getAsDouble();
结果:10.0
//平均值
Double d4 = uList.stream().mapToDouble(UserInfo::getNum).average().getAsDouble();
结果:37.666666666666664//除了统计double类型,还有int和long,bigDecimal需要用到reduce求和
DecimalFormat df = new DecimalFormat("0.00");//保留两位小数点
//和;可过滤掉NULL值
BigDecimal add = uList.stream().map(UserInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal add = uList.stream().filter(s->t.getPrice()!=null).map(UserInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add)
System.out.println(df.format(add));
结果:129.00
//最大
Optional<UserInfo> max = uList.stream().max((u1, u2) -> u1.getNum().compareTo(u2.getNum()));
System.out.println(df.format(max.get().getPrice()));
结果:99.00
//最小
Optional<UserInfo> min = uList.stream().min((u1, u2) -> u1.getNum().compareTo(u2.getNum()));
System.out.println(df.format(min.get().getPrice()));
结果:10.00
//求和,还有mapToInt、mapToLong、flatMapToDouble、flatMapToInt、flatMapToLong
list.stream().mapToDouble(UserInfo::getNum).sum();
//最大
list.stream().mapToDouble(UserInfo::getNum).max();
//最小
list.stream().mapToDouble(UserInfo::getNum).min();
//平均值
list.stream().mapToDouble(UserInfo::getNum).average();
//获取N个List中,最大数组长度
List<OrderExcelOut> valueList = new ArrayList<>();
List<List<TagOut>> tagList = valueList.stream().filter(v -> v.getTagList() != null && v.getTagList().size() > 0).map(OrderExcelOut::getTagList).collect(Collectors.toList());
Optional<List<TagOut>> maxTagList = tagList.stream().max((u1, u2) -> Integer.valueOf(u1.size()).compareTo(u2.size()));
//数组中最长的数组
maxTagList.get().size();
 

未完,待续...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_38983.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频编解码 - RTP 与 RTCP

目录 RTP 实时传输协议 RTCP协议 将H264 RTP打包 RTP 实时传输协议 音视频数据传输&#xff0c;先将原始数据经过编码压缩后&#xff0c;将码流打包成一个个RTP包&#xff0c;再将码流传输到接收端。 打包的作用 接收端要正确地使用这些音视频编码数据&#xff0c;不仅仅需…

JaVers:自动化数据审计

在开发应用程序时&#xff0c;我们经常需要存储有关数据如何随时间变化的信息。此信息可用于更轻松地调试应用程序并满足设计要求。在本文中&#xff0c;我们将讨论 JaVers 工具&#xff0c;该工具允许您通过记录数据库实体状态的更改来自动执行此过程。 Javers如何工作&#x…

vue Router

Vue项目各文件含义 1.src文件夹 是我们真正敲代码的文件夹&#xff0c; 2.assets放静态资源 3.components放组件 4.App.vue主组件 5.main.js项目的入口文件 Vue Router 在router/index.js路由文件中配置路由&#xff0c;设置路由跳转规则 import Vue from vue import Vu…

android Framework 中用到了哪些跨进程通信方式?

文章目录Linux 有哪些跨进程的通信方式&#xff1f;管道本地 Socket共享内存信号Linux 有哪些跨进程的通信方式&#xff1f; Binder 机制是Android基于Linux的一种独特的IPC机制。我们常用的AMS&#xff0c;PMS 等都是通过Binder机制来完成跨进程通信的&#xff0c;那么除了Bin…

【并发】深入理解Java线程的底层原理

线程基础知识 线程与进程 进程 操作系统会以进程为单位&#xff0c;分配系统资源&#xff08;CPU时间片、内存等资源&#xff09;&#xff0c;进程是资源分配的最小单位。 当一个程序被运行&#xff0c;从磁盘加载这个程序的代码至内存&#xff0c;这时就开启了一个进程。 线…

使用 Mason 创建自己的 Flutter brick

使用 Mason 创建自己的 Flutter brick 原文 https://medium.com/gytworkz/create-your-own-flutter-brick-using-mason-7abc70d0324e 前言 谁不喜欢用最少的努力完成大部分事情呢&#xff1f;我当然知道! &#xff01;Mason 帮我完成了几个简单的步骤。 在本文中&#xff0c;我…

Redis——》数据类型:List(列表)

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 Redis——》数据类型&#xff1a;List&#xff08;列表&#xff09;一、简介…

复现黑客在后门中藏匿后门

PHP实现在后门中藏匿后门 在攻击渗透的时候会传入shell后门方便进行远控。其中的后门包括多种类型&#xff0c;大马是功能最全的直接提供了可视化的界面方便攻击者进行提权、扫描、上传等一系列的操作。 但有很多hacker不讲武德&#xff0c;在写好的大马中藏入自己的后门&…

VBA Regex 正则表达式应用介绍

. VBA正则表达式介绍 正则表达式或 RegEx 用于在字符串中查找特定的字符。 本文将展示一个 VBA RegEx 示例,并演示为什么在 VBA 中使用正则表达式如此强大。 正则表达式是一个比较大的话题,关于这方面的书很多。 同时也是一个让许多人感到害怕的话题,因为它的语法比较神秘和…

C++入门笔记

C 入门笔记Functions in CC header Files下面主要是我学习C的一个笔记&#xff0c;记录学习中遇到的一些重点事项。下面是视频的连接https://www.bilibili.com/video/BV1Ay4y1i7Z6/?p10&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourcee6e…

记录--两行CSS让页面提升了近7倍渲染性能!

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 对于前端人员来讲&#xff0c;最令人头疼的应该就是页面性能了&#xff0c;当用户在访问一个页面时&#xff0c;总是希望它能够快速呈现在眼前并且是可交互状态。如果页面加载过慢&#xff0c;你…

第四章. Pandas进阶—时间序列

第四章. Pandas进阶 4.9 时间序列 1.重采样&#xff08;resample&#xff09; 在Pandas中&#xff0c;对时间序列频率的调整称为重采样&#xff0c;即时间序列从一个频率转换到另一个频率的过程&#xff0c;由周统计变成月统计 1).语法&#xff1a; 4.8章 第4点 已介绍过&…

MySQL数据库行级锁之间隙锁、临键锁

间隙锁 默认情况下&#xff0c;InnoDB在 REPEATABLE READ事务隔离级别运行&#xff0c;InnoDB使用 next-key 锁进行搜索和索引扫描&#xff0c;以防止幻读。 索引上的等值查询(唯一索引)&#xff0c;给不存在的记录加锁时, 优化为间隙锁 。索引上的等值查询(非唯一普通索引)&…

如果把网络原理倒过来看,从无到有,一切如此清晰(下)

人生若只如初见。 前言 当我在台灯下&#xff0c;听着远隔17年前五月天的歌&#xff0c;而在数日后&#xff0c;我的文字也会纵使相隔万里远的来到你的屏幕前&#xff0c;就觉得这一切妙不可言。 OSI 网络七层模型 《如果把网络原理倒过来看&#xff0c;从无到有&#xff0c…

Seal库官方示例(二):encoders.cpp解析

补充一个常用的SIMD操作原理 图片来自的Hang Shao的文章。 完整代码 这个代码主要功能是编码明文&#xff0c;使得能够使用更加完整的明文多项式&#xff08;前一个只用到了一个多项式的常量&#xff09;&#xff0c;也就是SIMD操作。主要包含了两个部分&#xff0c;一个是BG…

HLS + ffmpeg 实现动态码流视频服务

一、简介 如下图&#xff0c;包含三部分&#xff0c;右边一列为边缘节点&#xff1b;中间一列代表数据中心&#xff1b;左边一列是项目为客户提供的一系列web管理工具&#xff1a; 具体来说在我们项目中有一堆边缘节点&#xff0c;每个节点上部署一台强大的GPU服务器及N个网络…

精彩回顾 | 苏州农商银行新一代云原生信息科技架构体系实践

11月18日&#xff0c;2022年第五届中国金融科技产业大会暨第四届中新&#xff08;苏州&#xff09;数字金融应用博览会“基础软件与云原生系统软件”分论坛成功举办。该论坛由由中国计算机学会CTO CLUB&#xff08;苏州&#xff09;承办&#xff0c;江苏省金融科技云原生融合创…

目标检测数据标注项目分析-产品缺陷检测

什么是生产过程中的产品缺陷检测? 生产过程中的缺陷检测是保证产品质量的重要环节。及时发现故障或缺陷&#xff0c;并采取适当的措施&#xff0c;我们可以降低运行和质量相关的风险。但在一般视觉系统中&#xff0c;每个缺陷都必须经过检查及预处理才能被检测到&#xff0c;…

javaSE - Arrays - 数组的定义与使用

一、数组基本用法 1.1、什么是数组 数组本质上就是让我们能 “批量” 创建相同类型的变量 也可以说是存储一组相同数据类型的数据的集合 如: 如果需要表示两个数据, 那么直接创建两个变量即可 int a; int b 如果需要表示五个数据, 那么可以创建五个变量 int a1; int a2; int …

[附源码]Python计算机毕业设计Django的4s店车辆管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…