我想减去两个ArrayLists,这样我可以让孩子不在另一个列表中。
我是这样做的:
removeIDs=(ArrayList<Integer>) storedIDs.clone();
removeIDs.removeAll(downloadedIDs);
downloadIDs=(ArrayList<Integer>) downloadedIDs.clone();
downloadIDs.removeAll(storedIDs);
问题是这两个列表都包含5000个孩子,我的androidphone上花了将近4秒。
有快速的方法吗? 是否更快地使用集合?(我在列表中没有重复的值)
我开发了一个Android应用程序
答案 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。