作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

最近公司新来了一个小伙伴,问了磊哥一个比较“奇怪”的问题,这个问题本身的难度并不大,但比较“隐蔽”,那究竟是什么问题呢?接下来我们一起来看。

起因

最近公司的系统要增加一个新的列表展示功能,功能本身难度并不大,但遇到了一个很“可怪”的问题。小伙伴在执行查询列表时,明明已经使用了 order by 进行排序了,但最终查询出来的数据却还是乱的。

预期中的(正确)结果:现实中的(非预期)结果:那到底是哪里出现了问题呢?

问题展示

为了方便展示,我把复杂的业务程序简化成了以下代码:

import java.util.HashMap;public class App {public static void main(String[] args) {HashMap<String, Object> result = getList();result.forEach((k, v) -> {System.out.println(k + ":" + v);});}// 查询方法(简化版)public static HashMap<String, Object> getList() {HashMap<String, Object> result = new HashMap<>(); // 最终返回的结果集// 伪代码:从数据库中查询出了数据,然后对数据进行处理之后,存到了for (int i = 1; i <= 5; i++) {result.put("2022-10-" + i, "hello java" + i);}return result;}
}

以上程序的执行结果如下:

预期的结果应该是按时间的先后顺序展示的,如下图所示:

PS:以上示例代码中,插入元素的顺序是有序的(从 1 到 5),相当于实际业务场景中的 order by。

原因分析

既然原数据使用了 order by 排序,那么原数据肯定是没问题的,那问题就只会出现在返回集 HashMap 上,然后我们再把焦点放到 HashMap 上, 瞬间醒悟,哦,原来如此。HashMap 使用的是哈希方式进行存储的,因此存入和读取的顺序可能是不一致的,这也说 HashMap 是无序的集合,所以会导致插入的(或 order by 的)顺序,与最终展示的顺序不一致。

解决方案

经过上面的分析我们顺利找到了问题,那接下来就是制定相应的解决方案了,我想到的解决方案有两个:

  1. 稍微麻烦一点但正确的解决方案:将返回的不确定数据类型 HashMap 改为确定的数据类型,比如 List;

  2. 简单一点但并不是最优的解决方案:将无序的 HashMap 改为有序的 LinkedHashMap,此方案的优点是,只需要改动一个单词就可以解决整个问题了。

第一种解决方案大家都懂这里就不演示了,接下来咱们使用第二种解决方案将上面的问题改造一下,最终的实现代码如下:

import java.util.HashMap;
import java.util.LinkedHashMap;public class App {public static void main(String[] args) {HashMap<String, Object> result = getList();result.forEach((k, v) -> {System.out.println(k + ":" + v);});}// 查询方法(简化版)public static HashMap<String, Object> getList() {HashMap<String, Object> result = new LinkedHashMap<>(); // 最终返回的结果集// 伪代码:从数据库中查询出了数据,然后对数据进行处理之后,存到了for (int i = 1; i <= 5; i++) {result.put("2022-10-" + i, "hello java" + i);}return result;}
}

以上程序的执行结果如下:从上述结果可以看出,当使用 LinkedHashMap 替代了 HashMap  之后,返回的顺序就能和插入的顺序保持一致了。

LinkedHashMap 的魔力

为什么 HashMap 是无序的,而 LinkedHashMap 却是有序的呢?

这要从二者的实现说起了,LinkedHashMap 属于 HashMap 的子类,所以 LinkedHashMap  除了拥有 HashMap 的所有特性之后,还具备自身的一些扩展属性,其中就包括 LinkedHashMap 中额外维护了一个双向链表,这个双向链表就是用来保存元素的(插入)顺序的,这也是为什么 LinkedHashMap 可以实现访问顺序和插入顺序一致的原因了。

总结

本文演示了 HashMap 作为返回类型时隐藏的一个小“坑”,因为 HashMap 本身是无序的,所以它会导致查询顺序和插入顺序不一致的问题,对应的解决方案有两种:使用确定的数据类型来替代 HashMap,比如 List,或者使用有序的 LinkedHashMap 来替代无序的 HashMap。

关注公众号「Java中文社群」查看更多 Java 总结性系列文章。

往期推荐

Java 中 List 分片的 5 种方法!

阿里二面:为什么要分库分表?

50行代码,搞定敏感数据读写!

HashMap 中的一个“坑”!相关推荐

  1. 记前端状态管理库Akita中的一个坑

    记状态管理库Akita中的一个坑 Akita是什么 Akita是一种基于RxJS的状态管理模式,它采用Flux中的多个数据存储和Redux中的不可变更新的思想,以及流数据的概念,来创建可观察的数据存储 ...

  2. 由安卓开发中的一个坑引发的问题解决之道浅析

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 扯扯 最近发生了好多事情,两会,google AI alphaGo 大战李世石,俘获无数少男少女心的韩国电视剧<太 ...

  3. AngularJs在IE10,11中的一个坑。

    2019独角兽企业重金招聘Python工程师标准>>> 最近项目在做IE10,11的兼容性测试,发现$http的get方法只会下发一次请求,经过查询,才得知是因为IE强制缓存了get ...

  4. react dispatch_记 react 项目在 TypeScript 化中的一个坑,以及相应的类型改动

    最近向 @types/react 提交了一个变动,改动了 useReducer 的定义,相信各位读者如果要 TypeScript 化,或者已经 TS 化的话,有可能会收到影响. 通过安装 @types ...

  5. 在Java中==的一个坑

    观察下面代码,输出结果是什么? public static void main(String[] args) {Integer p = 10000;Integer q = 10000;System.o ...

  6. try-with-resources 中的一个坑,注意避让

    小伙伴们好呀,昨天复盘以前做的项目(大概有一年了),看到这个  try-catch ,又想起自己之前掉坑的这个经历 ,弄了个小 demo 给大家感受下~  

  7. HashMap中傻傻分不清楚的那些概念

    转载自 HashMap中傻傻分不清楚的那些概念 很多人在通过阅读源码的方式学习Java,这是个很好的方式.而JDK的源码自然是首选.在JDK的众多类中,我觉得HashMap及其相关的类是设计的比较好的 ...

  8. linux编译动态库未定义,GCC链接库的一个坑:动态库存在却提示未定义动态库的函数...

    背景 在GCC中已经指定链接库,然而编译时却提示动态库函数未定义! 测试出现的错误提示如下: [GMPY@13:48 tmp]$gcc -o test -L. -lmylib test.c /tmp/ ...

  9. php限制一个函数在几分钟内不被调用_在PHP一句话木马使用过程中的种种坑点分析...

    前言 在平时的学习和练习过程中,经常会遇到上传的一句话木马无法执行我们的命令或者说能执行命令但是不能连接菜刀蚁剑等webshell管理工具,以及各个版本PHP所限制的一些一句话木马的写法,不同版本we ...

最新文章

  1. Leetcode 168. Excel表列名称 解题思路及C++实现
  2. 使用python重命名某个文件下的所有的文件
  3. 鸿蒙os2.0系统什么时候,鸿蒙OS 2.0beta什么时候发布 鸿蒙OS2.0功能介绍
  4. C语言extern与static修饰变量
  5. CSS自学笔记(15):CSS3多列布局
  6. 计算机科学导论2000字报告,《计算机科学导论》(节选)翻译报告
  7. 51单片机智能小车——超声波
  8. C++拷贝构造函数专题
  9. 解决webview无法调用支付宝
  10. 如何面对软件工程师考试?
  11. linux安装seaweedfs
  12. python获取excel整行数据如何保存到新的工作簿中_如何使用python将大量数据导出到Excel中的小技巧之一...
  13. 2015华为南研所校园招聘笔试面试经历
  14. tm1650中文资料_TM1650+msp430单片机 调试及遇到问题的总结
  15. linux格式化分区4t硬盘,Linux下挂载4T大小usb硬盘的经历
  16. 【rtthread番外】第三篇:套接字抽象层SAL
  17. JZOJ5006. A
  18. 数字视频基础知识简介
  19. Maker 注释中的小问题
  20. 旺店通·企业奇门与金蝶云星空对接集成查询销售出库单连通[旺店通][销售出库单标准新增]-v1(旺店通->金蝶销售出库单--零售销售(手工运维))

热门文章

  1. 山海伏妖录java_山海伏妖录攻略大全 剧情结局加点妖兽大全
  2. 使用validate验证数据库
  3. 跋山涉水——深入 Redis 字典遍历
  4. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API
  5. 苹果再次拒绝协助美国政府解锁纽约毒品案中的iPhone
  6. 步骤1:JMeter 录制脚本接口测试
  7. UVA 12501 Bulky process of bulk reduction ——(线段树成段更新)
  8. 黑马程序员——选择排序
  9. jQuery-input输入框下拉提示层
  10. 明白90/10的原理吗?