哈喽,大家好呀!我是小米,一个爱折腾代码的技术分享狂,最近迷上了研究面试题,尤其是那些看似简单却暗藏玄机的!今天,我们来聊聊 Java 中的 TreeMap、TreeSet 和 Collections.sort(),它们是如何比较元素进行排序的。话不多说,咱们从一个小故事开始吧。 故事的开端:小明的面试现场 小明是一位 Java 开发者,最近在准备跳槽,迎来了心仪公司的技术面试。面试官一上来就问了他一个问题: “TreeMap 和 TreeSet 在排序时是如何比较元素的?你能详细说说吗?” 小明心里一紧,但还是冷静回答道:“TreeMap 和 TreeSet 是有序的,它们依赖元素的自然顺序或一个自定义的比较器进行排序。” 面试官追问:“那它们具体是如何实现排序的呢?” 小明脑海中闪过平时的学习笔记,赶紧回忆起了重点。 TreeMap 和 TreeSet 背后的大佬——红黑树 TreeMap 和 TreeSet 底层都基于 红黑树,这是一种自平衡二叉搜索树。红黑树确保每次插入或删除操作后,树的高度始终保持平衡,查找和插入的时间复杂度是 O(logn)。 比较元素的两种方式 在排序元素时,TreeMap 和 TreeSet 都需要比较元素来决定在树中的位置。它们支持两种比较方式: 1、自然顺序 (Natural Ordering) 如果存储的元素实现了 Comparable 接口(如 String 和 Integer),会默认使用元素的 compareTo() 方法来比较。例如:
这里的 TreeSet 使用的是 String 的自然顺序,即字母顺序。 2、自定义比较器 (Comparator) 如果想要自定义排序规则,可以通过构造器传入一个 Comparator 实例。例如:
上面的代码中,TreeMap 使用了一个自定义比较器,实现了降序排序。 面试官的追击:深入 Collections.sort() 面试官接着问了小明第二个问题:“那 Collections.sort() 是如何比较元素的呢?” 小明瞬间冒出一句:“Collections.sort() 本质上是对列表进行排序,它依赖元素的自然顺序或自定义比较器。” 底层排序算法:TimSort 小明补充道,Collections.sort() 的实现其实是基于 Arrays.sort(),而 Arrays.sort() 使用了一种名为 TimSort 的排序算法。这是一种混合排序算法,结合了归并排序和插入排序的优点。 示例代码:自然顺序排序
示例代码:自定义排序规则
小明解释说,Collections.sort() 会先检查传入的列表是否实现了 Comparable 接口,如果没有实现,就需要提供一个 Comparator 实现排序逻辑。 拓展:TreeMap、TreeSet 和 Collections.sort() 的对比 为了更好地回答面试官的问题,小明还梳理了一下三者的异同:
面试官的最后一击:为什么 TreeMap/TreeSet 的比较方式这么重要? 面试官笑着问:“既然 TreeMap 和 TreeSet 依赖比较器,那比较方式会带来哪些问题呢?” 小明稳住情绪,说道:“比较方式直接影响数据的存储和检索。如果比较器不正确,可能会导致逻辑错误,例如重复元素无法正确识别、顺序不符合预期等。” 他举了一个例子:
在这个例子中,自定义比较器总是返回 0,导致 TreeSet 认为所有元素都相等,结果只存储了第一个添加的元素。 故事的结尾:小明的面试通过了! 面试结束后,面试官对小明的回答表示满意,还夸他理解得很到位!小明开心极了,立刻跑去吃了一顿大餐庆祝。 END 看完这个小故事,大家对 TreeMap、TreeSet 和 Collections.sort() 的比较方式是不是更清晰了呢?如果你觉得还有点晕,不妨自己动手写点代码实验一下!理解 Java 的奥秘,实践才是王道呀! 最后,大家有什么面试题想让我解析,或者对本文有什么问题,欢迎在评论区留言哦!你的每一个互动,都是我继续分享的动力~ 我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!