𝗠𝗮𝘀𝘁𝗲𝗿 𝗝𝗮𝘃𝗮 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻𝘀

大多数开发者默认使用 ArrayList 或 HashSet。这对于简单的任务可行,但在需要速度或规模时,它会失效。

我曾经用一个普通的 ArrayList 构建过游戏排行榜。每次分数变化时,我都会对其进行排序。结果导致 UI 不断卡顿。我当时是在与语言作对,而不是在利用它。

停止使用错误的工具。使用这三种专门的集合来编写更快、更简洁的代码。

  1. 用于枚举常量的 EnumSet

如果你对枚举使用 HashSet,你会付出性能代价。每次插入都会将枚举装箱(box)为对象,这增加了不必要的开销。

EnumSet 使用位向量(bit vector)。它通过单条 CPU 指令进行检查。

Before: Set abilities = new HashSet<>(); abilities.add(Ability.FIRE);

After: EnumSet abilities = EnumSet.of(Ability.FIRE);

  1. 用于范围查询的 NavigableSet

手动遍历排序列表来查找范围既慢又容易出错。你经常会遇到“差一错误”(off-by-one bugs)。

NavigableSet 会自动保持数据有序。它为子集提供 O(log n) 的查找效率。

Before: Collections.sort(scores); List topTen = scores.subList(size - 10, size);

After: NavigableSet scores = new TreeSet<>(Comparator.reverseOrder()); scores.add(1542); NavigableSet topTen = scores.headSet(scores.first(), true).stream().limit(10).collect(Collectors.toCollection(TreeSet::new));

  1. 用于读多写少列表的 CopyOnWriteArrayList

在 ArrayList 上使用同步块(synchronized blocks)会减慢每次读取的速度。如果一个线程在写入而另一个线程在读取,还会导致 ConcurrentModificationException。

CopyOnWriteArrayList 在每次写入时都会创建数组的一个新副本。读取者查看的是数组的一个快照。

Before: List log = Collections.synchronizedList(new ArrayList<>()); // Iterating here can crash if a writer joins in.

After: CopyOnWriteArrayList log = new CopyOnWriteArrayList<>(); // Iteration is safe and never crashes.

别再只会默认使用那两种集合了。请根据你的数据模式选择最合适的工具。

来源:https://dev.to/timevolt/the-java-collections-force-mastering-the-hidden-gems-like-a-jedi-4438