首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ArrayList移除与removeAll

ArrayList移除与removeAll
EN

Stack Overflow用户
提问于 2015-03-01 12:50:35
回答 2查看 4.8K关注 0票数 6

如果我想从数组列表中删除一个集合,还有什么更好的吗?我认为removeAll方法在ArrayList中是为这个任务编写的,但是在我编写的测试中,迭代对象和单独删除对象要快几秒钟。

你用什么做这个用途?

编辑:

我在grepcode上找到的removeAll代码调用batchRemove (c,false):

私有布尔多...batchRemove(集合c,布尔补码){

代码语言:javascript
复制
700         final Object[] elementData = this.elementData;
701         int r = 0, w = 0;
702         boolean modified = false;
703         try {
704             for (; r < size; r++)
705                 if (c.contains(elementData[r]) == complement)
706                     elementData[w++] = elementData[r];
707         } finally {
708             // Preserve behavioral compatibility with AbstractCollection,
709             // even if c.contains() throws.
710             if (r != size) {
711                 System.arraycopy(elementData, r,
712                                  elementData, w,
713                                  size - r);
714                 w += size - r;
715             }
716             if (w != size) {
717                 // clear to let GC do its work
718                 for (int i = w; i < size; i++)
719                     elementData[i] = null;
720                 modCount += size - w;
721                 size = w;
722                 modified = true;
723             }
724         }
725         return modified;
726     }

我真的不明白..。

我的测试代码是:

代码语言:javascript
复制
public class RemoveVsRemovall {

    public static void main(String[] args){
        ArrayList<String> source = new ArrayList<>();
        ArrayList<String> toRemove = new ArrayList<>();
        for(int i = 0; i < 30000; i++){
            String s = String.valueOf(System.nanoTime());
            source.add(s);
            if(i % 2 == 0) toRemove.add(s);
        }
        long startTime = System.nanoTime();
        removeList1(source, toRemove);
        long endTime = System.nanoTime();
        System.out.println("diff: " + (endTime - startTime) * 1e-9);
    }

    static void removeList1(ArrayList<String> source, ArrayList<String> toRemove){
        source.removeAll(toRemove);
    }

    static void removeList2(ArrayList<String> source, ArrayList<String> toRemove){
        for(String s : toRemove){
            source.remove(s);
        }
    }
}

用不同的列表大小调用它几次,并在这两种方法之间切换。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-01 13:09:14

这个问题很难给出一般性的答案,这有几个原因。

首先,您必须理解这些性能特征是依赖于实现的。实现很有可能因JDK的平台和版本而有所不同。

话虽如此,实现removeAll的策略主要有2种

  1. 对于ArrayList的每个元素,检查它是否位于另一个Collection中;如果是,则删除它。
  2. 对于Collection的每个元素,检查它是否在ArrayList中;如果是,则删除它。

如果Collection在恒定时间内执行包含,策略1(渐近)获胜.另一方面,如果通过扫描整个连接来执行contains,并且Collection迭代非常慢,策略2通常具有优势,因为它只在Collection上迭代一次;但是即使在这种情况下,如果Collection非常大而且ArrayList的大多数元素都在Collection的最初元素中,那么策略1再次获胜.这是没有尽头的。

您最好相信removeAll()的实现;如果失败,尝试更改数据结构;如果也失败,则通过经验基准实现您自己的方法。

票数 4
EN

Stack Overflow用户

发布于 2015-03-01 13:17:56

另一件需要考虑的事情是:

Java代码经过了很长时间的测试,它的编写是为了适应许多不同的特殊情况(请参阅注释Preserve behavioral compatibility with AbstractCollection)。

因此,实际上,很可能您可以编写自己的方法实现,这将运行得更快。但另一方面,您确定您可以处理Java开发人员自Java诞生以来所面临的所有特殊情况吗?

还要考虑到一些Java函数可能正在使用一些C实现来加快速度。这里的情况显然不是这样,但可以。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28793733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档