Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中从ArrayList中删除对象_Java_Performance_Memory Management_Arraylist - Fatal编程技术网

在Java中从ArrayList中删除对象

在Java中从ArrayList中删除对象,java,performance,memory-management,arraylist,Java,Performance,Memory Management,Arraylist,如果满足条件,我需要从ArrayList中删除一些对象,我想知道哪种方法更有效 情况是这样的:我有一个类,它包含一个ArrayList,其中包含一些其他对象。我必须迭代这个ArrayList,并删除满足特定条件的所有元素。 据我所知,我可以选择删除以下内容: 创建一个新的ArrayList,并添加不符合条件的元素。迭代后,将旧的arraylist交换到新的arraylist,而不使用元素 创建一个新的ArrayList,并添加满足条件的元素。迭代后,使用removeAll()方法传递ArrayL

如果满足条件,我需要从
ArrayList
中删除一些对象,我想知道哪种方法更有效

情况是这样的:我有一个类,它包含一个
ArrayList
,其中包含一些其他对象。我必须迭代这个
ArrayList
,并删除满足特定条件的所有元素。 据我所知,我可以选择删除以下内容:

  • 创建一个新的
    ArrayList
    ,并添加不符合条件的元素。迭代后,将旧的arraylist交换到新的arraylist,而不使用元素

  • 创建一个新的
    ArrayList
    ,并添加满足条件的元素。迭代后,使用
    removeAll()
    方法传递
    ArrayList
    和要删除的对象


  • 是否有更有效的方法从
    ArrayList
    删除对象?

    另一种方法:迭代器有一个可选的remove()-方法,该方法是为ArrayList实现的。您可以在迭代时使用它

    但我不知道哪种变体的性能最好,你应该测量一下


    星蓝评论说,复杂度不好,这也是正确的(对于ReaveALL()也是如此),因为ArrayList必须复制所有元素,如果中间元素是添加或移除的元素。在这种情况下,LinkedList应该工作得更好。但是,由于我们都不知道您的实际用例,最好的方法是测量所有变体,以选择最佳解决方案?JDK的默认集合类应该包含所有支持此方法的creator迭代器。

    您可以在遍历ArrayList时向后迭代并删除。这样做的优点是后续元素不需要移动,并且比向前移动更容易编程。

    首先,我要确保这确实是一个性能瓶颈,否则我会选择最干净、最具表现力的解决方案


    如果这是一个性能瓶颈,只需尝试不同的策略,看看什么是最快的。我的赌注是创建一个新的ArrayList并将所需的对象放入其中,丢弃旧的ArrayList。

    显然,在您提到的两种方法中,第1种更有效,因为它只需要遍历列表一次,而使用第2种方法,列表必须遍历两次(首先查找要删除的元素,然后单击它们以删除它们)

    实际上,从另一个列表中删除元素列表可能是一种比O(n)更糟糕的算法,因此方法2更糟糕

    迭代器方法:

    List data = ...;
    
    for (Iterator i = data.iterator(); i.hasNext(); ) {
        Object element = i.next();
    
        if (!(...)) {
            i.remove();
        }
    }
    

    我猜,最有效的方法是使用该方法并进行反向迭代:

    for (ListIterator<E> iter = list.listIterator(list.size()); iter.hasPrevious();){
        if (weWantToDelete(iter.previous()))  iter.remove();
    }
    

    这可能是清理集合的最佳方法。由于它使用内部迭代,集合实现可以采用快捷方式使其尽可能快(对于
    ArrayList
    s,它可以将所需的复制量降至最低).

    除非你肯定你面临的问题确实是一个瓶颈,否则我会选择可读的

    public ArrayList filterThings() {
    
        ArrayList pileOfThings;
        ArrayList filteredPileOfThings = new ArrayList();
    
        for (Thing thingy : pileOfThings) {
            if (thingy.property != 1) {
                filteredPileOfThings.add(thingy);
            }            
        }
        return filteredPileOfThings;
    }
    

    我很赞成Mnementh的建议。
    不过有一个警告

     ConcurrentModificationException
    

    请注意,您没有运行多个线程。如果执行多个线程,并且线程没有很好地同步,则可能会出现此异常。

    从ArrayList中删除元素会产生隐藏成本。每次删除元素时,都需要移动元素以填补“漏洞”。对于一个包含N个元素的列表,平均需要
    N/2
    个赋值

    因此,从N元素数组列表中删除M个元素平均是
    O(M*N)

    List data = ...;
    List newData = new ArrayList(data.size()); 
    
    for (Iterator i = data.iterator(); i.hasNext(); ) {
        Object element = i.next();
    
        if ((...)) {
            newData.add(element);
        }
    }
    
    如果N很大,我猜想对于小到3或4的M值,这种方法将比
    remove
    方法更快


    但是创建足够大的
    newList
    以容纳
    list
    中的所有元素非常重要,以避免在扩展备份数组时复制备份数组。

    我找到了另一种更快的解决方案:

      int j = 0;
      for (Iterator i = list.listIterator(); i.hasNext(); ) {
        j++;
    
        if (campo.getNome().equals(key)) {
           i.remove();
           i = list.listIterator(j);
        }
      }
    
    int-sizepuede=listaoptionVO.size();
    对于(int i=0;i

    编辑:使用迭代器添加缩进,您可以始终处理按顺序排列的元素,而不是指定的索引。因此,您不应该为上述问题而烦恼

    Iterator itr = list.iterator();
    String strElement = "";
    while(itr.hasNext()){
    
      strElement = (String)itr.next();
      if(strElement.equals("2"))
      {
        itr.remove();
      }
    

    虽然这是违反直觉的,但我还是以这种方式大大加快了这项操作

    正是我在做的:

    ArrayList < HashMap < String , String >> results; // This has been filled with a whole bunch of results
    
    ArrayList>results;//这里已经填充了一大堆结果
    
    ArrayList>discard=findResultsToDiscard(结果)

    结果:全部移除(丢弃)

    然而,remove all方法(不包括获取丢弃结果的方法)需要6秒以上的时间才能从2000个数组(ish)中删除大约800个结果

    我在这篇文章中尝试了gustafc和其他人建议的迭代器方法

    这确实稍微加快了操作速度(下降到4秒左右),但这仍然不够好。所以我尝试了一些冒险的方法

     ArrayList < HashMap < String, String>> results;
    
      List < Integer > noIndex = getTheDiscardedIndexs(results);
    
    for (int j = noIndex.size()-1; j >= 0; j-- ){
        results.remove(noIndex.get(j).intValue());
    }
    
    ArrayList>结果;
    ListnoIndex=getthediscardedindex(结果);
    对于(int j=noIndex.size()-1;j>=0;j--){
    results.remove(noIndex.get(j.intValue());
    }
    
    虽然GetTheDiscardedIndex保存的是一个索引数组,而不是一个HashMaps数组。事实证明,删除对象的速度要快得多(现在约为0.1秒),而且内存效率更高,因为我们不需要创建一个大的结果数组来删除


    希望这对其他人有所帮助。

    但是
    remove()
    有一个警告:它可能不会删除您当前正在查看的对象。引用JavaDoc:更正式
    ArrayList < HashMap < String , String >> results; // This has been filled with a whole bunch of results
    
     ArrayList < HashMap < String, String>> results;
    
      List < Integer > noIndex = getTheDiscardedIndexs(results);
    
    for (int j = noIndex.size()-1; j >= 0; j-- ){
        results.remove(noIndex.get(j).intValue());
    }