3 回答
TA贡献1805条经验 获得超10个赞
为了使其更具可读性,在这种情况下有Collection::addAll并Collection::removeAll使用,您的代码可以是:
// create a new Collection where you use filter to search only the Object you want
Collection<Object> filterdCollection = myFirstCollection.stream()
.filter(o -> conditionReturningTrue(o))
.collect(Collectors.toCollection(LinkedHashSet::new));
// use allAll to add all the filtered Object to the second collection
mySecondCollection.addAll(filterdCollection);
// use removeAll to remove all the filtered Object from the first collection
myFirstCollection.removeAll(filterdCollection);
TA贡献1810条经验 获得超4个赞
首先,你应该争取正确。对于大多数集合,禁止在迭代时修改源集合。您可能会ConcurrentModificationException尝试一段时间,但即使它碰巧无一例外地运行,代码仍然不正确。只是这个错误并不总是被检测到(这是一个尽力而为的检查,试图避免浪费太多的性能)。这适用于forEach(…)、 以及stream().forEach(…)和 for-each 循环 ( for(variable declaration: collection))
在迭代时删除元素的唯一支持是通过手动Iterator使用:
for(Iterator<Object> it = myFirstCollection.iterator(); it.hasNext(); ) {
Object o = it.next();
if(conditionReturningTrue(o)) {
it.remove();
mySecondCollection.add(o);
}
}
替代方法是批量方法。
首先,就像这个和那个答案中所示,创建要首先传输的所有元素的副本。
其次,您可以使用
myFirstCollection.removeIf(o -> conditionReturningTrue(o) && mySecondCollection.add(o));
的default实现removeIf使用了Iterator一个类似于上面的循环。但是,像这样的集合ArrayList提供了它们自己的 实现removeIf,以克服Iterator循环的二次时间复杂度。
TA贡献1900条经验 获得超5个赞
您可以通过避免removeAll(对于某些Collection对象查找需要线性搜索的Lists ,例如s,这可能需要二次时间)来提高性能,方法是使用Collectors.partitioningBy将原始文件拆分Collection为两个Lists:
Collection<Object> myFirstCollection; //let's consider it instanciated and populated
Collection<Object> mySecondCollection; //same for this one
Map<Boolean,List<Object>> partition =
myFirstCollection.stream()
.collect(Collectors.partitioningBy(o -> conditionReturningTrue(o)));
myFirstCollection.clear();
myFirstCollections.addAll(partition.get(false));
mySecondCollection.addAll(partition.get(true));
另一方面,如果只有少数元素应该从 移动myFirstCollection到,则此解决方案可能效率较低mySecondCollection。
添加回答
举报