最近公司新来了一个小伙伴,问了磊哥一个比拟“奇怪”的问题,这个问题自身的难度并不大,但比拟“荫蔽”,那到底是什么问题呢?接下来咱们一起来看。
起因
最近公司的零碎要减少一个新的列表展现性能,性能自身难度并不大,但遇到了一个很“可怪”的问题。小伙伴在执行查问列表时,明明曾经应用了 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 的)程序,与最终展现的程序不统一。
解决方案
通过下面的剖析咱们顺利找到了问题,那接下来就是制订相应的解决方案了,我想到的解决方案有两个:
- 略微麻烦一点但正确的解决方案:将返回的不确定数据类型 HashMap 改为确定的数据类型,比方 List<T>;
- 简略一点但并不是最优的解决方案:将无序的 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<T>,或者应用有序的 LinkedHashMap 来代替无序的 HashMap。
关注公众号「Java中文社群」查看更多 Java 总结性系列文章。