【问题标题】:How can I Subtract these lists faster?我怎样才能更快地减去这些列表?
【发布时间】:2013-02-28 13:46:51
【问题描述】:

我想减去两个 ArrayList,这样我就可以拥有不在另一个列表中的孩子。

我是这样做的:

removeIDs=(ArrayList<Integer>) storedIDs.clone();
removeIDs.removeAll(downloadedIDs);

downloadIDs=(ArrayList<Integer>) downloadedIDs.clone();
downloadIDs.removeAll(storedIDs);

问题是两个列表都包含 5000 个孩子,在我的安卓手机上需要将近 4 秒。

有没有快速的方法来做到这一点? 使用集合更快吗?(我在列表中没有重复值)

我开发了一个安卓应用

【问题讨论】:

    标签: java android performance arraylist


    【解决方案1】:

    除非您需要保持顺序,否则请使用 HashSet 而不是 ArrayList。

    移除一个元素需要扫描完整的 List 以实现列表,相比之下,HashSet 只是计算哈希码,然后识别目标桶。

    【讨论】:

      【解决方案2】:

      套装应该更快。现在,它基本上是在做一个 n^2 循环。它遍历 removeIDs 中的每个元素并检查该 id 是否在下载的IDs 中,这需要搜索整个列表。如果将下载的 ID 存储在搜索速度更快的东西中,例如 HashSet,这会快得多并且变成 O(n) 而不是 O(n^2)。 Collections API 中可能还有更快的东西,但我不知道。

      如果您需要保留排序,您可以使用 LinkedHashSet 而不是普通的 HashSet,但它会增加一些偷听的内存和插入/删除元素的一些性能损失。

      【讨论】:

        【解决方案3】:

        我同意 HashSet 建议,除非整数 ID 适合相对较小的范围。在这种情况下,我将使用 HashSet 和 BitSet 中的每一个进行基准测试,并实际使用对您的环境中的数据更快的那个。

        【讨论】:

          【解决方案4】:

          首先,我为冗长的回答道歉。如果我在任何时候错了,随时欢迎您纠正我。这里我比较了一些解决方案的选项

          选项 1 :

          在您的代码中,您使用了ArrayList.removeAll 方法,让我们看看 removeAll 的代码

          removeAll的源码

          public boolean removeAll(Collection<?> c) {
                  return batchRemove(c, false);
              }
          

          所以需要知道batchRemove 方法中的内容。这里是link。如果你能看到这里的关键部分

          for (; r < size; r++)
                   if (c.contains(elementData[r]) == complement)
                           elementData[w++] = elementData[r];
          

          现在让我们看看contains 方法,它只是indexOf 方法的包装。 link。在 indexOf 方法中有一个 O(n) 操作。 (这里只注意一部分)

           for (int i = 0; i < size; i++)
                      if (elementData[i]==null)
                              return i;
          

          总之它是一个

          O(n^2)

          removeAll中的操作

          选项 2 : 以前我在这里写过一些东西,但似乎我在某些时候错了,所以删除了它。最好听取专家关于 Hashset 的建议。我不确定在你的情况下 hashmap 是否会是一个更好的解决方案。所以我提出了另一种解决方案

          选项3 :

          第 1 步:如果您的数据已排序,则无需此步骤,否则对您要减去的列表进行排序(第二个列表)

          第 2 步:对未排序列表的每个元素在第二个列表中运行二进制搜索

          第 3 步:如果未找到匹配项,则存储在另一个结果列表中,但如果找到匹配项则不添加

          第 4 步:结果列表是您的最终答案

          选项 3 的成本:

          第1步:如果没有排序O(nlogn)时间

          第 2 步: O(nlogn) 时间

          第三步:O(n)空格

          **

          所以总体 O(nlogn) 时间和 O(n) 空间

          **

          【讨论】:

            【解决方案5】:

            如果需要列表,您可以选择LinkedList。在您的情况下,正如@Chris 所说, ArrayList 实现将在每次删除中移动所有元素。

            使用 LinkedList,您将获得更好的随机添加/删除性能。看到这个post

            【讨论】:

              猜你喜欢
              • 2023-03-18
              • 2020-04-06
              • 2020-09-04
              • 1970-01-01
              • 2023-02-13
              • 2019-12-16
              • 1970-01-01
              • 1970-01-01
              • 2017-12-20
              相关资源
              最近更新 更多