如何更快地减去这些列表?

时间:2013-03-12 20:32:19

标签: java android performance arraylist

我想减去两个ArrayLists,这样我可以让孩子不在另一个列表中。

我是这样做的:

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

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

问题是这两个列表都包含5000个孩子,我的androidphone上花了将近4秒。

有快速的方法吗? 是否更快地使用集合?(我在列表中没有重复的值)

我开发了一个Android应用程序

5 个答案:

答案 0 :(得分:7)

除非您需要保留订单,否则请使用HashSet而不是ArrayList。

删除元素需要扫描列表实现的完整列表,比较HashSet只是计算哈希码,然后识别目标桶。

答案 1 :(得分:1)

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

如果你需要保存服务器订购,你可以使用LinkedHashSet而不是普通的HashSet,但它会添加一些内存,但是插入/删除元素会有一些性能损失。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

选项1&lt; ArrayList&gt;:

在您使用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&lt; HashSet&gt;: 以前我在这里写了一些东西,但似乎我在某些方面错了所以删除它。最好接受专家关于Hashset的建议。在您的情况下,我不确定hashmap是否是更好的解决方案。所以我建议另一个解决方案

选项3&lt;我的建议您可以尝试&gt;:

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

对于未排序列表的每个元素,

步骤2:在第二个列表中运行二进制搜索

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

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

选项3的费用:

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

第2步: O(nlogn)时间

第3步: O(n)空间

**

  

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

**

答案 4 :(得分:0)

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

使用LinkedList,您可以获得更好的随机添加/删除性能。请参阅此post