HashMap 中的一个“坑”!

021aff58a559faf7b55478cdaf86204f.png

作者 | 王磊

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

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

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

起因

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

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

问题展示

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

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;}
}

以上程序的执行结果如下:29248c1191ee82b016539547a9fbb923.png

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

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;}
}

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

LinkedHashMap 的魔力

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

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

总结

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

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

7b6aa3a818100cd5a2ce1e142cd4d7fc.gif

往期推荐

36699d3314c491593111dc90d96121bc.png

Java 中 List 分片的 5 种方法!


1af4946c0962c0d3d6dc1f0309a07eb8.png

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


38aa7541b31d1de7c69be9344949a484.png

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


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

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

相关文章

【Python】交互式界面创建函数

文章目录简介规则思路示例代码与运行效果简介 运行Python时&#xff0c;在程序运行过程中手动输入一个函数表达式&#xff0c;并将其作为一个函数进行后续的调用工作&#xff0c;类似于Matlab里面的匿名函数。这个功能使用传统语言会相当麻烦&#xff0c;当然&#xff0c;我也…

原生 js前端路由系统实现3之代码 构建工具 和 querystring功能

为什么80%的码农都做不了架构师&#xff1f;>>> 构建 目前前端构建工具流行的是 grunk.js 功能是大而全&#xff0c;但往往大而全的东西为了多样性 需要做额外的配置 我还是想要有一个专门为自己特性项目而生构建工具 我不想加载第三方的node模块&#xff0c;也不…

单例模式,真不简单

前言单例模式无论在我们面试&#xff0c;还是日常工作中&#xff0c;都会面对的问题。但很多单例模式的细节&#xff0c;值得我们深入探索一下。这篇文章透过单例模式&#xff0c;串联了多方面基础知识&#xff0c;非常值得一读。1 什么是单例模式&#xff1f;单例模式是一种非…

【python】最优化方法之一维搜索(黄金分割法+斐波那契法)

文章目录1.概念2.遍历搜索3.优化算法3.1.一维搜索原则3.2.黄金分割法Code Block3.3.斐波拉契法Code Block1.概念 \qquad一维搜索是最优化方法最简单的一种&#xff0c;即求一个在(a,b)内&#xff0c;连续下单峰函数f(x)f(x)f(x)的极小值。所谓下单峰函数就是只有一个极小值的函…

MySQL系列之E-1------MySQL主从复制原理

主从复制是异步复制,可以通过google的一个插件实现半同步E.1 主从复制原理1、建立主从复制的用户名和密码2、将master上主库需要进行复制的库“锁库”3、通过mysqldump备份master上主库&#xff0c;“解锁“&#xff0c;在slave端进行恢复4、更改配置文件5、在丛库上执行change…

Java Long类的valueOf()方法及示例

Syntax: 句法&#xff1a; public static Long valueOf (long value);public static Long valueOf (String value);public static Long valueOf (String value, int radixs);长类valueOf()方法 (Long class valueOf() method) valueOf() method is available in java.lang pac…

工作中常用的 6 种设计模式!

前言 哈喽&#xff0c;大家好。平时我们写代码呢&#xff0c;多数情况都是流水线式写代码&#xff0c;基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢&#xff0c;我觉得&#xff0c;最好的方式就是&#xff1a;使用设计模式优化自己的业务代码。今天跟大家聊聊日常工作中…

【Matlab/C/Python/VB/...】代码复制到word时如何变成彩色的

文章目录下载Notepad复制代码在Notepad粘贴在word中粘贴下载Notepad Notepad是一款免费的Windows软件&#xff0c;一般Windows10和Windows7系统都已经自带&#xff0c;也可以在应用商店直接搜索下载 「win10系统兼容的是7.8版本」 复制代码 在语言编辑乱码复制代码&#xff…

Java Formatter toString()方法与示例

格式化程序类toString()方法 (Formatter Class toString() method) toString() method is available in java.util package. toString()方法在java.util包中可用。 toString() method is for the string representation of this Formatter. toString()方法用于此Formatter的字符…

hadoop 2.5.0安装和配置

安装hadoop要先做以下准备&#xff1a; 1.jdk&#xff0c;安装教程在 http://www.cnblogs.com/stardjyeah/p/4640917.html 2.ssh无密码验证&#xff0c;配置教程在 http://www.cnblogs.com/stardjyeah/p/4641524.html 3.linux静态ip配置&#xff0c;教程在 http://www.cnblo…

基于双线性插值的图像旋转原理及MATLAB实现(非自带函数)

目录1.图像旋转的原理1.1.旋转矩阵1.2.双线性插值1.3.像素点匹配2.实现效果与说明1.图像旋转的原理 1.1.旋转矩阵 旋转一幅图像&#xff08;假设这幅图像大小是矩形的&#xff09;&#xff0c;当然应该从像素点&#xff08;pixels&#xff09;开始&#xff0c;在直角坐标系中…

漫画:给女朋友介绍什么是 “元宇宙” ?

什么是更高的自由度呢&#xff1f;或许有人觉得&#xff0c;我们在网络游戏当中&#xff0c;不是也很自由吗&#xff1f;想怎么玩就怎么玩。但是&#xff0c;无论一款网络游戏的元素有多么丰富&#xff0c;游戏当中的角色、任务、职业、道具、场景&#xff0c;都是游戏设计师预…

document.createElement

document.createElement()的用法document.createElement()是在对象中创建一个对象&#xff0c;要与appendChild() 或 insertBefore()方法联合使用。其中&#xff0c;appendChild() 方法在节点的子节点列表末添加新的子节点。insertBefore() 方法在节点的子节点列表任意位置插入…

double.isnan_Java Double类isNaN()方法与示例

double.isnanSyntax: 句法&#xff1a; public boolean isNaN ();public static boolean isNaN(double value);双类isNaN()方法 (Double class isNaN() method) isNaN() method is available in java.lang package. isNaN()方法在java.lang包中可用。 isNaN() method is used …

MyBatis 中为什么不建议使用 where 1=1?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;最近接手了一个老项目&#xff0c;“愉悦的心情”自然无以言表&#xff0c;做开发的朋友都懂&#xff0c;这里就不多说了&am…

【openMV与机器视觉】四旋翼飞行控制背景下的PID控制与摄像头算法简介

文章目录声明1.四旋翼飞行控制简介2.飞行控制算法2.1.接收机PWM生成2.2.PID算法位置PID速度PID3.摄像头算法3.1.图像处理3.2.霍夫曼变换3.3.巡线算法3.3.寻找目标点降落算法声明 \qquad本文的算法在openMV IDE例程的基础上进行原创&#xff0c;在比赛结束后予以发表&#xff1b…

Java BigDecimal valueOf()方法与示例

BigDecimal类的valueOf()方法 (BigDecimal Class valueOf() method) Syntax: 句法&#xff1a; public static BigDecimal valueOf (double d);public static BigDecimal valueOf (long l);public static BigDecimal valueOf (long unsc_val , int sc_val);valueOf() method i…

关于liaoxuefeng的python3教程实战第四天

关于liaoxuefeng的python3教程实战第四天。地址&#xff1a;http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432338991719a4c5c42ef08e4f44ad0f293ad728a27b000#0编写数据访问代码接下来&#xff0c;就可以真正开始编写代码操作对象了…

聊聊sql优化的15个小技巧

前言sql优化是一个大家都比较关注的热门话题&#xff0c;无论你在面试&#xff0c;还是工作中&#xff0c;都很有可能会遇到。如果某天你负责的某个线上接口&#xff0c;出现了性能问题&#xff0c;需要做优化。那么你首先想到的很有可能是优化sql语句&#xff0c;因为它的改造…

没有安装node对等点依赖_功能依赖项的对等 数据库管理系统

没有安装node对等点依赖Equivalence of Functional dependencies states that, if the relations of different Functional dependencies sets are given, then we have to find out whether one Functional dependency set is a subset of other given set or both the sets a…