来自推荐一个程序员编程资料站http://cxyroad.com副业赚钱专栏https://xbt100.top2024年IDEA最新激活方法后台回复激活码CSDN免登录复制代码插件下载CSDN复制插件以下是正文。最后细数一次 JDK8 踩过的坑往后再不干了重复的事情不应该再做第二遍否则是对生命的不尊重。❝ 本文主要内容JDK8 踩过的坑内容基础。❞「⏱️踩坑的原因未知和遗忘。」本文主要内容第一类 API只有特定参数值才会引发异常相关 API具体描述Collectors.toMap1. 重复值 Duplicate key 错误.....2. value 的 function 计算结果 null 引发 NPEparallelStream 并行流1. ThreadLocal#get() 为 null2. 非安全类数据异常stream#sort 排序排序字段为 null引发 NPE多字段排序常发生java.util.Optional#get/ofof 入参为 null引发 NPEget#value 为 null 异常 ....第二类 API只要运行一次就能察觉错误相关 API具体描述stream#peek非终止 API遇到终止 API 才会执行stream 只能消费一次stream has already been operated upon or closed注下文内容为上面表格的举例说明。Collectors.toMap关于 Collectors.toMap 的易错点主要有两个:key 计算结果重复场景还原具体描述从 DB 查询 List 数据 将 List 转换成 Map方便下一个循环的匹配查找业务执行过程出现了脏数据key 不再唯一引发错误key 是由 Function 方法计算而来Function 计算结果重复引发错误下面案例模拟数据重复值toMap 时出现 duplicate keyMapString, String map Arrays.asList(A, A) .stream() .collect(Collectors.toMap(str - str, Function.identity()));防止脏数据等异常数据一定指定 mergeFunction请使用下面 API 进行 toMaptoMap(Function? super T, ? extends K keyMapper, Function? super T, ? extends U valueMapper, BinaryOperatorU mergeFunction)值为 null场景还原具体描述从 DB 中获取的对象数据进行 toMapvalue 的字段被某业务场景更新为 null 了(或丢失更新)。value 是由 Function 方法计算而来Function 计算为 null下面案例value 值由函数值返回模拟返回 null 运行结果 NPEprivatestatic String returnNull(){ returnnull; } publicstaticvoidmain(String[] args){ MapString, String map Arrays.asList(A, A) .stream() .collect(Collectors.toMap(str - str, str - returnNull(), (first, second) - first)); }parallelStream❝遇到最大的坑直接将 stream 修改成 parallelStream 天真地以为做了性能优化。❞常见 stream 流操作中有 DB 查询、远程 API 等耗时操作直接将 stream 修改成 parallelStream 做优化并行流ThreadLocal#get 异常非线程安全类异常parallelStream 是多线程并行流容易出现多线程问题场景还原具体描述ThreadLocal#get 数据有时候正确ThreadLocal 与当前线程有关系ArrayList 返回条目数不对ArrayList 不是线程安全类下面案例相同代码执行两次结果线程名称不一致。执行第一次执行第二次ThreadLocal 异常的情况模拟用户应用上下文最终获取为 null其他场景不再赘述一定要知道 parallelStream 是并行的多线程的问题它都有。特别注意「数据量小不易察觉」性能优化不能仅仅将 stream 修改成 parallelStream 血泪经验......stream#sort排序字段 null多字段排序在 tob 业务常见常因为第二、三个字段为 null 排序出现 NPE场景还原具体描述业务查询结果先按第一个字段排序相同再按照第二个字段排序......stream 不同于数据库的排序操作为 null 时数据库会默认排序但这个API不会案例模拟从 DB 检索出来的数据按照业务要求进行多字段排序往事同事第一次用这个 API 就出现了线上故障≡(▔﹏▔)≡如果排序字段有可能为空有需要排序可在比较器中加入Comparator.nullsLast(String::compareTo)orComparator.nullsFirst(String::compareTo)为空的会放在前面或后面Optional#get/ofget/ofOptional 被引入用来解决 NPE但下面这两个 API 却容易出现异常 of 入参为 null 抛 NPEget 返回值检查 value 为 null 抛 NoSuchElementException下面是 java.util.Optional#get 方法源码public T get(){ if (value null) { thrownew NoSuchElementException(No value present); } return value; }题外话Optional 是我个人非常喜欢的一个类大大减少了 NPE比如我还用它作出参入参。形如下面public T,R OptionalT function(OptionalR param){ ..... }其他再啰嗦一下边边角角的 APIstream只能消费一次运行一次就知道用错误了好多流的 API 也是只能消费一次下面案例stream 用了多次出现错误peek 方法peek 用的很少个人不推荐用初衷为了 debug 。peek 遇到终止类的 API 才执行。下面案例convenientMap 并不会插入新的元素。只有添加了一些终止操作才会执行。例如collect(Collectors.toList()), forEach等。// toMap 功能 ListTask taskList instTaskBO.getInstanceId(instance.getInstanceId()); MapString, Task convenientMap new HashMap(); // 将 list 转成map taskList.stream().peek(task - convenientMap.put(String.valueOf(task.getId()), task));其他8的日期不熟用的少坑不知道CompletableFuture考虑异常情况join 设置时长下面案例对于异常给一个默认的返回值// 异常情况给一个默认值 private CompletableFutureInteger calculate(SupplierInteger supplier){ return CompletableFuture .supplyAsync(() - invokeTask(supplier)) .exceptionally(throwable - { log.error(....., throwable); return0; }); }总结本文总结个人在使用 JDK8 踩过的坑内容基础。但总结是比较花费精力后面尽量总结研究一些高级点的东西~~~END推荐阅读副业赚钱推荐让你的时间开始变现免费体验AI图片生成就在 Image Generator Hub程序员在线工具站cxytools.com 推荐一个自己写的工具站https://cxytools.com专为程序员设计包括时间日期、 JSON处理、SQL格式化、随机字符串生成、UUID生成、文本Hash...等功能提升开发效 率。 ⬇戳阅读原文直达 朕已阅
细数一些 JDK8 踩过的坑,说多了都是泪
发布时间:2026/5/24 12:40:46
来自推荐一个程序员编程资料站http://cxyroad.com副业赚钱专栏https://xbt100.top2024年IDEA最新激活方法后台回复激活码CSDN免登录复制代码插件下载CSDN复制插件以下是正文。最后细数一次 JDK8 踩过的坑往后再不干了重复的事情不应该再做第二遍否则是对生命的不尊重。❝ 本文主要内容JDK8 踩过的坑内容基础。❞「⏱️踩坑的原因未知和遗忘。」本文主要内容第一类 API只有特定参数值才会引发异常相关 API具体描述Collectors.toMap1. 重复值 Duplicate key 错误.....2. value 的 function 计算结果 null 引发 NPEparallelStream 并行流1. ThreadLocal#get() 为 null2. 非安全类数据异常stream#sort 排序排序字段为 null引发 NPE多字段排序常发生java.util.Optional#get/ofof 入参为 null引发 NPEget#value 为 null 异常 ....第二类 API只要运行一次就能察觉错误相关 API具体描述stream#peek非终止 API遇到终止 API 才会执行stream 只能消费一次stream has already been operated upon or closed注下文内容为上面表格的举例说明。Collectors.toMap关于 Collectors.toMap 的易错点主要有两个:key 计算结果重复场景还原具体描述从 DB 查询 List 数据 将 List 转换成 Map方便下一个循环的匹配查找业务执行过程出现了脏数据key 不再唯一引发错误key 是由 Function 方法计算而来Function 计算结果重复引发错误下面案例模拟数据重复值toMap 时出现 duplicate keyMapString, String map Arrays.asList(A, A) .stream() .collect(Collectors.toMap(str - str, Function.identity()));防止脏数据等异常数据一定指定 mergeFunction请使用下面 API 进行 toMaptoMap(Function? super T, ? extends K keyMapper, Function? super T, ? extends U valueMapper, BinaryOperatorU mergeFunction)值为 null场景还原具体描述从 DB 中获取的对象数据进行 toMapvalue 的字段被某业务场景更新为 null 了(或丢失更新)。value 是由 Function 方法计算而来Function 计算为 null下面案例value 值由函数值返回模拟返回 null 运行结果 NPEprivatestatic String returnNull(){ returnnull; } publicstaticvoidmain(String[] args){ MapString, String map Arrays.asList(A, A) .stream() .collect(Collectors.toMap(str - str, str - returnNull(), (first, second) - first)); }parallelStream❝遇到最大的坑直接将 stream 修改成 parallelStream 天真地以为做了性能优化。❞常见 stream 流操作中有 DB 查询、远程 API 等耗时操作直接将 stream 修改成 parallelStream 做优化并行流ThreadLocal#get 异常非线程安全类异常parallelStream 是多线程并行流容易出现多线程问题场景还原具体描述ThreadLocal#get 数据有时候正确ThreadLocal 与当前线程有关系ArrayList 返回条目数不对ArrayList 不是线程安全类下面案例相同代码执行两次结果线程名称不一致。执行第一次执行第二次ThreadLocal 异常的情况模拟用户应用上下文最终获取为 null其他场景不再赘述一定要知道 parallelStream 是并行的多线程的问题它都有。特别注意「数据量小不易察觉」性能优化不能仅仅将 stream 修改成 parallelStream 血泪经验......stream#sort排序字段 null多字段排序在 tob 业务常见常因为第二、三个字段为 null 排序出现 NPE场景还原具体描述业务查询结果先按第一个字段排序相同再按照第二个字段排序......stream 不同于数据库的排序操作为 null 时数据库会默认排序但这个API不会案例模拟从 DB 检索出来的数据按照业务要求进行多字段排序往事同事第一次用这个 API 就出现了线上故障≡(▔﹏▔)≡如果排序字段有可能为空有需要排序可在比较器中加入Comparator.nullsLast(String::compareTo)orComparator.nullsFirst(String::compareTo)为空的会放在前面或后面Optional#get/ofget/ofOptional 被引入用来解决 NPE但下面这两个 API 却容易出现异常 of 入参为 null 抛 NPEget 返回值检查 value 为 null 抛 NoSuchElementException下面是 java.util.Optional#get 方法源码public T get(){ if (value null) { thrownew NoSuchElementException(No value present); } return value; }题外话Optional 是我个人非常喜欢的一个类大大减少了 NPE比如我还用它作出参入参。形如下面public T,R OptionalT function(OptionalR param){ ..... }其他再啰嗦一下边边角角的 APIstream只能消费一次运行一次就知道用错误了好多流的 API 也是只能消费一次下面案例stream 用了多次出现错误peek 方法peek 用的很少个人不推荐用初衷为了 debug 。peek 遇到终止类的 API 才执行。下面案例convenientMap 并不会插入新的元素。只有添加了一些终止操作才会执行。例如collect(Collectors.toList()), forEach等。// toMap 功能 ListTask taskList instTaskBO.getInstanceId(instance.getInstanceId()); MapString, Task convenientMap new HashMap(); // 将 list 转成map taskList.stream().peek(task - convenientMap.put(String.valueOf(task.getId()), task));其他8的日期不熟用的少坑不知道CompletableFuture考虑异常情况join 设置时长下面案例对于异常给一个默认的返回值// 异常情况给一个默认值 private CompletableFutureInteger calculate(SupplierInteger supplier){ return CompletableFuture .supplyAsync(() - invokeTask(supplier)) .exceptionally(throwable - { log.error(....., throwable); return0; }); }总结本文总结个人在使用 JDK8 踩过的坑内容基础。但总结是比较花费精力后面尽量总结研究一些高级点的东西~~~END推荐阅读副业赚钱推荐让你的时间开始变现免费体验AI图片生成就在 Image Generator Hub程序员在线工具站cxytools.com 推荐一个自己写的工具站https://cxytools.com专为程序员设计包括时间日期、 JSON处理、SQL格式化、随机字符串生成、UUID生成、文本Hash...等功能提升开发效 率。 ⬇戳阅读原文直达 朕已阅