为了账号安全,请及时绑定邮箱和手机立即绑定

如何根据谓词有效地将对象从一个 java 集合转移到另一个 java 集合?

如何根据谓词有效地将对象从一个 java 集合转移到另一个 java 集合?

喵喵时光机 2021-09-15 15:23:26
首先,我希望这个问题以前没有被问过。我看了一点,找不到合适的答案:s我正在寻找一种在特定条件为真时将某些对象从一个集合移动到另一个集合的有效方法。目前,我会以一种非常简单的方式来做,但恐怕这可能不是最佳的:Collection<Object> myFirstCollection;  //let's consider it instanciated and populatedCollection<Object> mySecondCollection; //same for this onemyFirstCollection.stream().forEach(o -> {     if ( conditionReturningTrue(o) ) {        mySecondCollection.add(o);        myFirstCollection.remove(o);    }});你知道有什么更好的方法/更有效的方法吗?
查看完整描述

3 回答

?
holdtom

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);


查看完整回答
反对 回复 2021-09-15
?
慕莱坞森

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循环的二次时间复杂度。


查看完整回答
反对 回复 2021-09-15
?
梵蒂冈之花

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。


查看完整回答
反对 回复 2021-09-15
  • 3 回答
  • 0 关注
  • 225 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信