我想减去两个ArrayLists,这样我就可以让孩子不在另一个列表中。
我是这样做的:
removeIDs=(ArrayList<Integer>) storedIDs.clone();
removeIDs.removeAll(downloadedIDs);
downloadIDs=(ArrayList<Integer>) downloadedIDs.clone();
downloadIDs.removeAll(storedIDs);
问题是两个列表都包含5000个孩子,我的androidphone需要大约4秒钟。
有没有快速的方法来做到这一点?
是否更快地使用集合?(我在列表中没有重复的值)
我开发了一个Android应用程序
除非您需要保留订单,否则请使用HashSet而不是ArrayList。
删除元素需要扫描完整列表以进行列表实现,比较HashSet只是计算哈希码,然后识别目标桶。
集应该更快。现在,它基本上做了一个n ^ 2循环。它遍历removeIDs中的每个元素,并检查该id是否在downloadedIDs中,这需要搜索整个列表。如果下载的ID存储在更快的搜索内容中,就像HashSet一样,这将更快,并且变为O(n)而不是O(n ^ 2)。 Collections API中可能还有更快的东西,但我不知道。
如果你需要preserver命令,你可以使用LinkedHashSet而不是普通的HashSet,但它会添加一些内存,并且插入/删除元素会有一些性能损失。
我同意HashSet建议,除非整数ID适合相对较小的范围。在这种情况下,我将使用HashSet和BitSet中的每一个进行基准测试,并实际使用对您环境中的数据更快的数据。
首先,我为长期答复道歉。如果我在任何时候都错了,欢迎你纠正我。在这里,我将比较解决方案的一些选项
选项1 <ArrayList>:
在您的代码中,您使用了 ArrayList.removeAll
方法让我们查看removeAll的代码
removeAll的源代码
public boolean removeAll(Collection<?> c) {
return batchRemove(c, false);
}
所以需要知道里面是什么 batchRemove
方法。这里是 链接。如果你能看到,这里的关键部分
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
现在让我们来看看 contains
方法只是一个包装 indexOf
方法。 链接。在indexOf方法中有一个O(n)操作。 (注意只是这里的一部分)
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
总而言之,这是一个
为O(n ^ 2)
在...的运作 removeAll
选项2 <HashSet>:
以前我在这里写了一些东西,但似乎我在某些方面错了所以删除它。最好接受专家关于Hashset的建议。在您的情况下,我不确定hashmap是否是更好的解决方案。所以我提出另一个解决方案
选项3 <我的建议您可以尝试>:
步骤1: 如果您的数据已排序,则不需要此步骤,否则将对要减去的列表进行排序(第二个列表)
第2步: 对于未排序列表的每个元素,在第二个列表中运行二进制搜索
第3步: 如果找不到匹配,则存储在另一个结果列表中但如果找到匹配则不添加
步骤4: 结果列表是你的最终答案
备选方案3的费用:
步骤1: 如果没有排序 O(nlogn)
时间
第2步: O(nlogn)
时间
第3步: O(n)
空间
**
整体O(nlogn)时间和O(n)空间
**
如果需要列表,您可以选择一个 链表。在你的情况下,正如@Chris所说,ArrayList实现将移动每次删除中的所有元素。
使用LinkedList,您可以获得更好的随机添加/删除性能。看到这个 岗位。