JAVA8新特性(Stream API,LocalDate,LocalDateTime)

一. Stream API

1.1 基础
代码参数准备:
package com.weige.javaskillpoint.controller;import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class JAVA8 {@Datastatic class User {// 姓名private String name;// 手机号private String phone;// 年龄private Integer age;public User(String name, String phone, Integer age) {this.name = name;this.phone = phone;this.age = age;}}private static List<User> getUserList() {return new ArrayList<User>() {{add(new User("周润发", "166", 52));add(new User("周星驰", "155", 42));add(new User("刘德华", "177", 62));add(new User("伍佰", "188", 45));add(new User("周传雄", "133", 40));add(new User("甄子丹", "199", 45));}};}}
场景一:知道一个List<User>对象,如何获取List<User>的所有用户id?
    public static void main(String[] args) {// 知道一个List<User>对象,如何获取List<User>的所有用户手机号?List<User> userList = getUserList();List<String> phoneList = userList.stream().map(User::getPhone).collect(Collectors.toList());// 打印内容 - 所有用户手机号为 [166, 155, 177, 188, 133, 199]log.info("所有用户手机号为 " + phoneList);}
场景二:知道一个List<User>对象,如何获取List<User>中年龄大于50的用户?
    public static void main(String[] args) {// 知道一个List<User>对象,如何获取List<User>中年龄大于50的用户?List<User> userList = getUserList();List<User> filterUserList = userList.stream().filter(u -> u.getAge() > 50).collect(Collectors.toList());// 打印内容 - 年龄大于50的用户为 [JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]log.info("年龄大于50的用户为 " + filterUserList);}
场景三:知道一个List<User>对象,如何按照年龄从小到小排序,从大到小排序?
public static void main(String[] args) {// 知道一个List<User>对象,如何按照年龄从大到小排序?List<User> userList = getUserList();List<User> ascUserList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());List<User> reversedUserList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());// 打印内容 - 年龄从小到大 [JAVA8.User(name=周传雄, phone=133, age=40), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]log.info("年龄从小到大 " + ascUserList);// 打印内容 - 年龄从大到小 [JAVA8.User(name=刘德华, phone=177, age=62), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=周传雄, phone=133, age=40)]log.info("年龄从大到小 " + reversedUserList);}
场景四:知道一个List<User>对象,如何按照相同年龄进行分组,并获取分组后的数量?
public static void main(String[] args) {// 知道一个List<User>对象,如何按照相同年龄进行分组?List<User> userList = getUserList();Map<Integer, List<User>> groupingUserList = userList.stream().collect(Collectors.groupingBy(User::getAge));// 打印内容 - 相同年龄进行分组 {52=[JAVA8.User(name=周润发, phone=166, age=52)], 40=[JAVA8.User(name=周传雄, phone=133, age=40)], 42=[JAVA8.User(name=周星驰, phone=155, age=42)], 45=[JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45)], 62=[JAVA8.User(name=刘德华, phone=177, age=62)]}log.info("相同年龄进行分组 " + groupingUserList);// 知道一个List<User>对象,如何按照相同年龄进行分组后获取其对应数量?Map<Integer, Long> countUserList = userList.stream().collect(Collectors.groupingBy(User::getAge, Collectors.counting()));// 打印内容 - 相同年龄进行分组的数量 {52=1, 40=1, 42=1, 45=2, 62=1}log.info("相同年龄进行分组的数量 " + countUserList);}
1.2 进阶
场景一:有一张用户浏览记录表,一个用户可以有多条浏览记录,且有不同的浏览类型;比如小明浏览娱乐模块530秒,浏览军事模块600秒,则对应两个浏览记录数据。新建用户浏览类型统计表,根据现有的用户浏览记录表数据对用户浏览类型统计表进行新增,请用Stream优雅的实现该功能?
package com.weige.javaskillpoint.controller;import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Slf4j
public class JAVA8 {@Datastatic class History {// 用户idprivate Long userId;// 用户浏览类型 (1->娱乐 2->军事 3->教育)private Integer type;// 用户浏览时间(单位秒)private Long seconds;public History(Long userId, Integer type, Long seconds) {this.userId = userId;this.type = type;this.seconds = seconds;}}@Datastatic class HistoryStatistics {// 用户idprivate Long userId;// 用户浏览类型 (1->娱乐 2->军事 3->教育)private Integer type;// 浏览类型统计数量private Long count;public HistoryStatistics(Long userId, Integer type, Long count) {this.userId = userId;this.type = type;this.count = count;}}public static void main(String[] args) {// 模拟用户浏览记录数据List<History> historyList = new ArrayList<History>() {{add(new History(20231L, 1, 360L));add(new History(20231L, 1, 720L));add(new History(20231L, 2, 1360L));add(new History(20231L, 2, 2360L));add(new History(20239L, 2, 2360L));add(new History(20239L, 3, 360L));add(new History(20233L, 3, 360L));}};List<HistoryStatistics> insertHistoryStatisticsList = new ArrayList<>();// 根据用户id进行分组Map<Long, List<History>> groupingByUserIdMap = historyList.stream().collect(Collectors.groupingBy(History::getUserId));groupingByUserIdMap.forEach((key, value) -> {Map<Integer, Long> countMap = historyList.stream()// 筛选出对应用户id的浏览记录.filter(h -> key.equals(h.getUserId()))// 对用户id的浏览记录根据类型进行分组并获取数量.collect(Collectors.groupingBy(History::getType, Collectors.counting()));// 将用户浏览记录类型分组的数量Map转成List<HistoryStatistics>List<HistoryStatistics> historyStatisticsList = countMap.entrySet().stream().map(u -> new HistoryStatistics(key, u.getKey(), u.getValue())).collect(Collectors.toList());insertHistoryStatisticsList.addAll(historyStatisticsList);});// 批量新增用户浏览记录统计表batchInsertHistoryStatistics(insertHistoryStatisticsList);}public static void batchInsertHistoryStatistics(List<HistoryStatistics> insertHistoryStatisticsList) {log.info("------连接数据库------");log.info("------开始批量新增数据------");log.info("------批量新增数据: " + insertHistoryStatisticsList);log.info("------批量新增数据结束------");log.info("------关闭数据库连接------");}
}
场景二:有一张用户浏览记录表,一个用户可以有多条浏览记录,且有不同的浏览类型;比如小明浏览娱乐模块530秒,浏览军事模块600秒;小红浏览娱乐模块1000秒,浏览军事模块100秒,则对应四条浏览记录数据。想要得到每个用户总共的浏览时长,请用Stream优雅的实现该功能?
package com.weige.javaskillpoint.controller;import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Slf4j
public class JAVA8 {@Datastatic class History {// 用户姓名private String userName;// 用户浏览类型 (1->娱乐 2->军事 3->教育)private Integer type;// 用户浏览时间(单位秒)private Long seconds;public History(String userName, Integer type, Long seconds) {this.userName = userName;this.type = type;this.seconds = seconds;}}public static void main(String[] args) {List<History> historyList = new ArrayList<History>() {{add(new History("小明", 1, 360L));add(new History("小明", 1, 720L));add(new History("小明", 2, 1360L));add(new History("小明", 2, 2360L));add(new History("小红", 2, 2360L));add(new History("小白", 3, 360L));add(new History("小红", 3, 360L));add(new History("小白", 3, 1060L));}};// 串行流中reduce的第三个参数combiner无作用 返回值可以写为nullHashMap<String, Long> reduce = historyList.stream().reduce(new HashMap<>(), (m, e) -> {m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());return m;}, (m1,m2) -> null);// 返回结果 - {小明=4800, 小白=1420, 小红=2720}log.info("数据为: " + reduce);// 并行流中reduce的第三个参数combiner有作用 如果返回结果为map 则应用putAll()来解决并发情况下数据不一致问题 同时返回值应用ConcurrentHashMap接收ConcurrentHashMap<String, Long> parallelReduce = historyList.stream().parallel().reduce(new ConcurrentHashMap<>(), (m, e) -> {m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());return m;}, (m1,m2) -> {m1.putAll(m2);return m1;});// 返回结果 - {小明=4800, 小白=1420, 小红=2720}log.info("数据为: " + parallelReduce);// 这里举个例子:如果reduce第一个参数为1,则stream执行时,分两个阶段;// 第一个阶段分3步:1 + 1 = 2,1 + 2 = 3,1 + 3 = 4;// 第二个阶段 2 * 3 * 4 = 24List<Integer> intList = new ArrayList<Integer>(){{add(1);add(2);add(3);}};Integer sum = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer + integer2;}}, (integer, integer2) -> integer * integer2);// 返回结果 - 并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): 24log.info("并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): " + sum);Integer multipliers = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer + integer2;}});// 返回结果 - 并行流中第三个参数返回自己本身,不进行任何操作: 9log.info("并行流中第三个参数返回自己本身,不进行任何操作: " + multipliers);Integer num = intList.stream().reduce(1,Integer::sum);// 返回结果 - 串行流不使用第三个参数 7log.info("串行流不使用第三个参数 " + num);}}

二. LocalDate,LocalDateTime

2.1 基础
一般前端传给后端的时间参数,都是字符串拼接,比如"2023-07-19","2023 -07-19 20:00:00",这都是字符串;而查询数据库时,是需要根据Date时间类型来查询,所以这里需要将字符串转成Date,如果中间需要操作时间(年,月,日,时,分加减)
LocalDate
    public static void main(String[] args) {// 模拟前端传过来的时间参数String dateString = "2023-07-19";// 将字符串转成LocalDateTime  这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错// 2023-07-19 -> yyyy-MM-dd// LocalDate只能操作年 月 日LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));// 减1年LocalDate minusYears = localDate.minusYears(1);// 加1年LocalDate plusYears = localDate.plusYears(1);// 减1月LocalDate minusMonths = localDate.minusMonths(1);// 加1月LocalDate plusMonths = localDate.plusMonths(1);// 减1日LocalDate minusDays = localDate.minusDays(1);// 加1日LocalDate plusDays = localDate.plusDays(1);// 通过LocalDate操作时间参数得到自己想要的结果时 转换成Date类型查询数据库// LocalDate转DateDate date = localDateTurnDate(minusYears);getListByDate(date);System.out.println(date);}public static Date localDateTurnDate(LocalDate localDate) {ZoneId zone = ZoneId.systemDefault();Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();return Date.from(instant);}public static void getListByDate(Date date) {// 模拟查询结果ArrayList<String> arrayList = new ArrayList<String>() {{add("一辈子");add("下辈子");}};System.out.println("根据时间" + date + "查询结果为 : " + arrayList);}
LocalDateTime
    public static void main(String[] args) {// 模拟前端传过来的时间参数String dateString = "2023-07-19 20:20:20";// 将字符串转成LocalDateTime  这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错// 2023-07-19 20:20:20 -> yyyy-MM-dd HH:mm:ss// 2023-07-19 20:20 -> yyyy-MM-dd HH:mm// 2023-07-19 -> yyyy-MM-ddLocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));// 减1年LocalDateTime minusYears = localDateTime.minusYears(1);// 加1年LocalDateTime plusYears = localDateTime.plusYears(1);// 减1月LocalDateTime minusMonths = localDateTime.minusMonths(1);// 加1月LocalDateTime plusMonths = localDateTime.plusMonths(1);// 减1日LocalDateTime minusDays = localDateTime.minusDays(1);// 加1日LocalDateTime plusDays = localDateTime.plusDays(1);// 减1小时LocalDateTime minusHours = localDateTime.minusHours(1);// 加1小时LocalDateTime plusHours = localDateTime.plusHours(1);// 通过LocalDateTime操作时间参数得到自己想要的结果时 转换成Date类型查询数据库// LocalDateTime转DateDate date = localDateTimeTurnDate(minusYears);getListByDate(date);System.out.println(date);}public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();return Date.from(instant);}public static void getListByDate(Date date) {// 模拟查询结果ArrayList<String> arrayList = new ArrayList<String>() {{add("一辈子");add("下辈子");}};System.out.println("根据时间" + date + "查询结果为 : " + arrayList);}
2.2 进阶
对时间参数进行比较
通过当前时间,查询前6个小时数据库的数据
    public static void main(String[] args) {// 近6个小时String format = DateUtils.format(new Date(), "yyyy-MM-dd HH");LocalDateTime now = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));for (LocalDateTime currentdate = now.minusHours(5); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusHours(1)) {Date date = localDateTimeTurnDate(currentdate);getListByDate(date);}}public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();return Date.from(instant);}public static void getListByDate(Date date) {// 模拟查询结果ArrayList<String> arrayList = new ArrayList<String>() {{add("一辈子");add("下辈子");}};System.out.println("根据时间" + date + "查询结果为 : " + arrayList);}
通过当前时间,查询近7天数据库的数据
    public static void main(String[] args) {// 近7天String format = DateUtils.format(new Date(), "yyyy-MM-dd");LocalDateTime now = LocalDate.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();for (LocalDateTime currentdate = now.minusDays(6); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusDays(1)) {Date date = localDateTimeTurnDate(currentdate);getListByDate(date);}}public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();return Date.from(instant);}public static void getListByDate(Date date) {// 模拟查询结果ArrayList<String> arrayList = new ArrayList<String>() {{add("一辈子");add("下辈子");}};System.out.println("根据时间" + date + "查询结果为 : " + arrayList);}

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

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

相关文章

ElasticSearch搜索相关性及打分的相关原理

文章目录 一、相关性和打分简介二、TF-IDF得分计算公式三、BM25&#xff08;Best Matching 25&#xff09;四、使用explain查看TF-IDF五、通过Boosting控制相关度 一、相关性和打分简介 举个例子来说明&#xff1a; 假设有一个电商网站&#xff0c;用户在搜索框中输入了关键词&…

理解LLM中的ReAct

large language models (LLMs)大语言模型在语义理解和交互式决策方面有着不错的表现。ReAct在一次交互中循环使用推理和行动两个操作解决复杂问题&#xff0c;推理即利用模型自身语义理解能力&#xff0c;行动则利用模型以外的能力&#xff08;如计算、搜索最新消息&#xff0c…

架构训练营学习笔记:4-2 存储架构模式之复制架构

高可用的关键指标 问题&#xff1a;分为故障跟灾难。不是有了多活架构就不在用复制架构 &#xff0c;还是之前的合适原则&#xff1a;多活架构的技术复杂度 跟成本都比复制架构高。 高可用的关键指标 恢复时间目标(RecoveryTimeObjective&#xff0c;RTO)指为避免在灾难发生后…

Spring Cloud Gateway - 新一代微服务API网关

Spring Cloud Gateway - 新一代微服务API网关 文章目录 Spring Cloud Gateway - 新一代微服务API网关1.网关介绍2.Spring Cloud Gateway介绍3.Spring Cloud Gateway的特性4.Spring Cloud Gateway的三大核心概念5.Gateway工作流程6.Gateway核心配置7.动态路由8.Predicate自定义P…

阿里云RockMQ与SpringBoot的整合

前言&#xff1a; 开源版本Rocket和商业版本的RocketMQ有些不同&#xff0c;研究的是商业版本的RocketMQ&#xff0c;阿里云的官方文档&#xff0c;感觉有点乱。看不咋明白&#xff0c;网上虽然有教程&#xff0c;大都还是有点缺少&#xff0c;有时候会突然跳了步骤&#xff0c…

fpga4fun.com/Music box

1.Simple beep 先做一个简单地蜂鸣器&#xff0c;原理是晶振通过不同的分频器分成不同的频率&#xff0c;通过电路发出音调不同的声音。 例子中Pluto FPGA板子有25Mhz的时钟频率&#xff0c;采用16位计数器&#xff08;可以产生65536个不同的数值&#xff09;&#xff0c;则最…

C# 细说async/await的用法

目录 一&#xff0c;引言 二&#xff0c;实例演示 2.1 多线程同步执行下载任务&#xff0c;任务完成后通知 2.2 异步执行下载任务&#xff0c;任务完成后通知 三&#xff0c;async/await的用法 3.1 跨线程修改UI控件 3.2 异步获取数据 一&#xff0c;引言 首先先来区分…

网上书店管理系统

目录 一、系统需求分析 二、数据库概念结构设计 四、数据库物理实现 五、数据库功能调试 一、系统需求分析 需求概述 1.系统背景 当今互联网的迅速发展&#xff0c;使得人们获取信息变得极其便利。在从前&#xff0c;人们以线下书店购买书籍的方式获取知识&#xff0c;常常…

WEB:Confusion1

背景知识 SSTI漏洞 题目 根据网站图片和题目描述的提示&#xff0c;大象是php&#xff0c;蟒蛇是python&#xff0c;说明了这个网站是用python写的 在python中&#xff0c;比较常规的漏洞就是SSTI模板注入 没有思路&#xff0c;先点login和register页面看看 查看源代码 之前…

读论文---On Distillation of Guided Diffusion Models

该论文解决的问题 1 简要描述 2 在之前的工作中存在下述问题 计算过程需要计算: 1 unconditional的unet 2 conditional(w text)的unet 下图展示了计算过程 对应的代码 pipelines-> stable_diffusion-> pipline_stable_diffusion.py-> StableDiffusionPipeling-> 7…

C#在工业自动化领域的应用前景如何?

在2021年&#xff0c;C#与工业自动化已经开始结合&#xff0c;并且这种趋势有望在未来继续发展。C#是一种功能强大的编程语言&#xff0c;其面向对象的特性、跨平台支持以及丰富的类库和工具&#xff0c;使其成为在工业自动化领域应用的有力工具。 我这里刚好有嵌入式、单片机…

微服务系列文章 之 nginx日志格式分析以及修改

如何自定义日志格式&#xff0c;就需要修改nginx日志打印格式 一. 打开终端&#xff0c;登录服务器并输入服务器密码 //ssh 用户名服务器ip ssh root192.168.0.132二. 切换到nginx目录 cd /var/log/nginx/ 三. 查看nginx日志 tail -f access.log 日志说明&#xff1a; //…

Servlet的监听器

Servlet常用的监听器 ServletContextAttributeListener 用来感知ServlerContext对象属性变化&#xff0c;比如添加或删除属性变化 ServletContextListener 用来感知ServlerContext对象的创建和销毁的 ServletRequestListener 可以用来监听感知ServletRequest对象的创建和销毁的…

OLED拼接屏采购指南:如何选择最佳方案?

OLED拼接屏作为一种创新的大屏幕显示设备&#xff0c;正在成为各行各业信息展示和传播的重要工具。 然而&#xff0c;面对市场上众多的品牌和型号&#xff0c;如何选择最佳的OLED拼接屏方案成为一项关键任务。 本文将为您提供一份全面且实用的OLED拼接屏采购指南&#xff0c;…

.NET Native AOT的静态库与动态库

.NET不仅可以使用 C静态库与动态库&#xff0c;也可以将.NET实现的函数导出为C静态库与动态库。在没有Native Aot之前&#xff0c;.NET只能通过P/Invoke享受C/C生态&#xff0c;而在Native Aot之后&#xff0c;不仅可以享受这些生态&#xff0c;还可以开发SDK供其他语言调用。 …

蓝桥杯上岸每日N题第二期(一)!!!

大家好 我是寸铁&#x1f4aa; 考前需要刷大量真题,大家一起相互监督&#xff0c;每日做N题&#xff0c;一起上岸吧✌️ ~ 冲刺蓝桥杯省一模板大全来啦 &#x1f4a5; ~ 蓝桥杯4月8号就要开始了 &#x1f64f; ~ 还没背熟模板的伙伴们背起来 &#x1f4aa; &#x1f4aa; &…

Sql Server类型转换,Sql Server函数

CONVERT(数据类型, 表达式, 样式) --样式可以没有 CAST(表达式 as 数据类型) select StudentName 的出生日期是&#xff1a; cast(DateOfBirth as varchar(50)) as 学生信息 from Students; select StudentName 的出生日期是&#xff1a; convert(varchar(50), DateOfB…

WAIC2023会后记

听了3天WAIC的会&#xff0c; 大开眼界&#xff0c;算是上了堂大课。 本次参会的目的是听听AI企业信息化的想法、理论和实践。以进一步探索可能的业务场景。三天的会结束后&#xff0c;留下深刻印象的有如下几点。 大模型当道 2023这次大会的主题成了大模型&#xff0c;谈的…

基于单片机电子密码锁射频卡识别指纹门禁密码锁系统的设计与实现

功能介绍 通过指纹进行开锁或者是按键输入当前的密码&#xff0c;修改密码&#xff0c;对IC卡可以进行注册&#xff0c;删除。当有RFID卡进入到读卡器的读卡范围内时&#xff0c;则会自动读取卡序列号&#xff0c;单片机根据卡的序列号对卡进行判断。若该卡是有效卡&#xff0c…

SparkStreaming

SparkStreaming第一次运行时不丢失数据 auto.offset.reset earliest Kafka和SparkStreaming整合时&#xff1a; 注意&#xff1a;和SparkStreaming整合时&#xff0c;上面的可选参数是无效的&#xff0c;只有两个可选参数&#xff1a; smallest&#xff1a;简单理解为从头开…