Set 的有序性误区
在 Java 开发中,我们常听到'List 有序,Set 无序'的说法。这句话其实并不严谨,它更多是针对 HashSet 而言的。实际上,Set 接口下的不同实现类对顺序的支持各有不同。所谓的'无序',通常指元素没有固定的迭代顺序,但这不代表所有 Set 都丢失了顺序信息。
保持插入顺序:LinkedHashSet
如果你希望 Set 中的元素按照添加的顺序进行遍历,LinkedHashSet 是最佳选择。它在底层维护了一个双向链表,记录了元素的插入顺序。
Set<String> set = new LinkedHashSet<>();
set.add("B");
set.add("A");
set.add("C");
// 遍历结果:B, A, C
注意看这里的输出,虽然添加了 B、A、C,但遍历时依然保持了 B、A、C 的顺序。这就是因为它内部维护了链表结构,每次新增元素都会追加到链表尾部。
保持自然排序:TreeSet
若需要元素按特定规则(如字母表顺序或数值大小)排列,TreeSet 基于红黑树实现,会自动对元素进行排序。
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
// 遍历结果:1, 2, 3
这里要注意,元素必须实现 Comparable 接口,或者传入自定义的 Comparator,否则无法排序。实际开发中,如果业务强依赖顺序,千万别用 HashSet。
总结
选择 Set 实现时,不要默认认为它们都是无序的。根据业务需求,明确是需要插入顺序还是排序顺序,选择合适的实现类能让代码意图更清晰。


