【问题标题】:Optimizing the speed of insertion in java.util.Map/Set优化 java.util.Map/Set 中的插入速度
【发布时间】:2009-02-22 18:07:00
【问题描述】:

有没有办法通过指定项目的顺序来优化 java.util.Collection 中的插入速度?

例如

java.util.Set<String> set = java.util.TreeSet<String>();

这个解决办法:

set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");

比这个更快(随机顺序)?

set.add("E");
set.add("D");
set.add("C");
set.add("A");
set.add("B");

(对于其他集合也有同样的问题:HashMap、hastable...)

谢谢

【问题讨论】:

    标签: java algorithm collections insert performance


    【解决方案1】:

    简单的答案是“时间看看”。

    另一个答案是“没关系”。这似乎是一个微优化,几乎不值得付出努力。我认为它属于"The Sad Tragedy of Micro-Optimization Theater"的范畴。

    【讨论】:

    • 我在 BerkeleyDB 中存储了 很多 个对象。这些对象包含一个 Map 并且将这个映射读/写到一个字节数组可能是一个重要的因素。
    • @Pierre:如果您已经拥有 BerkleyDB,那么通过直接使用 DB 并对其进行正确调整,与插入冗余数据结构时可以进行的任何微优化相比,您将获得更高的性能。
    • @Pierre 将插入顺序插入 BDB 实际上会产生巨大的影响:至少对于本机 BDB,按密钥顺序插入比随机插入要快一个数量级(是的,我们已经对此进行了测试)。事实上,我们的处理是通过写入磁盘、归并排序、插入来完成的,组合比直接插入快 5 倍。但是尝试优化哈希/树映射不太重要,原因有多种((a)它不是瓶颈,bdb 会是;(b)可能没有任何优化)
    【解决方案2】:

    java.util.Map和java.util.Set不行,因为它们是接口,有不同的实现。

    对于具体的实现,这不是值得的优化。如果您遇到性能问题,请选择更合适的实现,或者重新考虑您需要存储什么以及如何存储。

    在普通笔记本电脑上,将 5000 个随机数插入 HashSet 大约需要一毫秒,那么您要插入多少百万个元素才能使这种优化变得有价值?

    【讨论】:

      【解决方案3】:

      red-black tree(用于实现 Java 的 TreeSet/TreeMap)的插入时间保证为 O(log n)。如果项目按特定顺序排列可能会更快,但我不确定那会是什么(可能预排序最快?)。

      插入哈希表是一个 O(1)(恒定时间)操作。插入的主要工作是计算hashcode


      编辑:Starblue 建议预排序可能会产生最差的性能,因此您可以尝试随机排序。

      【讨论】:

      • 预排序通常会导致很多不平衡,因此很可能是最坏的情况。
      • 我同意,如果您想加快速度,最好对列表进行排序,找到中间值,然后从中间值向两个方向插入。那时不需要重新排序子树。
      • 但是排序会花费更多的时间而不是稍后获得的时间。说到底这都是无用的微优化。
      【解决方案4】:

      基于散列的集合和基于树的集合之间自然存在巨大差异。

      基于树的对象受益于插入的元素排序(例如,字符串之间的比较),因此当您有可比较的对象(如字符串)时,最好使用它们。 TreeSet/TreeMap/等。在标准集合中应该是平衡的(红黑树),所以插入顺序并不重要。如果它不平衡,那么插入顺序就会很重要,因为您最终可能会得到一个链而不是树。

      在哈希表中,加载因子和哈希函数决定一切,但如果您正在处理字符串,您可能甚至不关心哈希会更好。

      如果您需要一组字符串来处理许多重叠的字符串,Trie 可能会更节省内存,但我认为库中没有。

      【讨论】:

        【解决方案5】:

        在采取优化措施时要小心考虑数据结构的特征。举一个极端的例子,将元素按排序顺序插入二叉树会产生一个链表。

        【讨论】:

        • 假设树没有重新平衡,我相信通常会这样做(至少对于 BDB 等)。
        猜你喜欢
        • 2018-07-14
        • 1970-01-01
        • 2012-09-29
        • 2017-02-08
        • 2021-09-20
        • 1970-01-01
        • 2010-10-26
        • 2012-04-03
        • 2011-08-01
        相关资源
        最近更新 更多