𝗠𝗮𝘀𝘁𝗲𝗿 𝗝𝗮𝘃𝗮 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻𝘀
大多数开发者默认使用 ArrayList 或 HashSet。这对于简单的任务可行,但在需要速度或规模时,它会失效。
我曾经用一个普通的 ArrayList 构建过游戏排行榜。每次分数变化时,我都会对其进行排序。结果导致 UI 不断卡顿。我当时是在与语言作对,而不是在利用它。
停止使用错误的工具。使用这三种专门的集合来编写更快、更简洁的代码。
- 用于枚举常量的 EnumSet
如果你对枚举使用 HashSet,你会付出性能代价。每次插入都会将枚举装箱(box)为对象,这增加了不必要的开销。
EnumSet 使用位向量(bit vector)。它通过单条 CPU 指令进行检查。
- 当你有一组固定的枚举值时使用它。
- 它减少了垃圾回收(GC)。
- 在密集循环中,它能提供 10 倍的速度提升。
Before:
Set
After:
EnumSet
- 用于范围查询的 NavigableSet
手动遍历排序列表来查找范围既慢又容易出错。你经常会遇到“差一错误”(off-by-one bugs)。
NavigableSet 会自动保持数据有序。它为子集提供 O(log n) 的查找效率。
- 用于高分排行榜或价格区间。
- 使用 headSet() 或 subSet() 来获取特定范围。
- 它消除了对手动排序代码的需求。
Before:
Collections.sort(scores);
List
After:
NavigableSet
- 用于读多写少列表的 CopyOnWriteArrayList
在 ArrayList 上使用同步块(synchronized blocks)会减慢每次读取的速度。如果一个线程在写入而另一个线程在读取,还会导致 ConcurrentModificationException。
CopyOnWriteArrayList 在每次写入时都会创建数组的一个新副本。读取者查看的是数组的一个快照。
- 用于事件监听器或配置设置。
- 当读取操作远多于写入操作时使用它。
- 它允许无锁读取。
Before:
List
After:
CopyOnWriteArrayList
别再只会默认使用那两种集合了。请根据你的数据模式选择最合适的工具。
来源:https://dev.to/timevolt/the-java-collections-force-mastering-the-hidden-gems-like-a-jedi-4438