【问题标题】:nullify object that is part of ArrayList java使作为 ArrayList java 一部分的对象无效
【发布时间】:2010-11-10 11:46:06
【问题描述】:

我有一个数组列表:

private ArrayList<PerfStatBean> statFilterResults;

我想像这样迭代它:

Iterator<PerfStatBean> statsIterator = statFilterResults.iterator();
while(statsIterator.hasNext()){
  i++;
  PerfStatBean perfBean = statsIterator.next();
  .........

我想在 while 循环中运行 statFilterResults 后从 statFilterResults 中删除 bean 以释放内存。我相信如果我做类似的事情

 perfBean = null;

它不会完成这项工作,因为 perfBean 引用将为空,但对象仍将在内存中。

有什么想法吗?

谢谢,

【问题讨论】:

    标签: java collections iterator


    【解决方案1】:

    ...我想在 while 循环中运行 statFilterResults 后从 statFilterResults 中删除 bean 以释放内存。

    如果在arraylist之外有另一个对象的引用,将它设置为null不会有任何区别,该对象的内存只使用一次,在java中你只能看到引用(或引用值)

    所以如果你有类似的东西:

    this.bean = new PerfStatBean();
    
    ....
    
    arrayList.add( this.bean );
    

    从列表中删除它不会有任何区别,因为原始引用仍然存在并且不会被 gc'ed。

    如果您在集合之外没有其他引用,即。

     arrayList.add( new PerfStatBean() );
    

    那么这就够了:

    while(....){
        .... 
    }
    
    arrayList.clear();
    

    因为这将删除对对象的引用,并使它们符合 gc 的条件。

    此外:如果您想“帮助”减少对象的引用数量,请调用:

    while(....){
        .... 
    }
    
    arrayList.clear();
    

    应该够了。

    【讨论】:

      【解决方案2】:

      为什么不在迭代后简单地清除列表?

      Iterator<PerfStatBean> statsIterator = statFilterResults.iterator();
      while(statsIterator.hasNext()){
        i++;
        PerfStatBean perfBean = statsIterator.next();
        .........
      }
      
      statFilterResults.clear();
      

      【讨论】:

        【解决方案3】:

        这可能不是一个很好的优化。如果内存需求很大,那么您可能首先不想将它们全部存储在一个列表中 - 在创建对象时处理它们。

        不过,从字面上看,ListIterator.set 是适合您的方法。

        for (
            ListIterator<PerfStatBean> iter = statFilterResults.listIterator();
            iter.hasNext()
        ) {
            ++i;
            PerfStatBean perfBean = iter.next();
            iter.set(null);
            ...
        }
        

        【讨论】:

          【解决方案4】:

          在 java 中,你真的不需要担心删除对象。如果下次垃圾收集器运行时没有对对象的引用,它将被删除(当有空闲 cpu 周期时运行 GC)。如果您希望确保直接删除对象,请使用 Runtime.getRuntime().gc()

          【讨论】:

            【解决方案5】:

            在循环之前创建一个集合,然后将要删除的任何项目添加到该集合中。循环结束后,调用

            statFilterResults.removeAll(beansToDelete);
            

            另外,顺便说一句,我发现使用 foreach 循环而不是迭代器通常更容易 - 更易读、更易于维护等。在你的情况下,这看起来像:

            for (PerfStatBean bean : statFilterResults) {
                ...
            }
            

            【讨论】:

            • 简单答案的好处:显然 OP 有足够的 RAM 来保存 ArrayList(它一开始就被填充了)。这将使所有内存立即可用于垃圾收集,而无需尝试手动调整。
            • 对于简单的 iterator.remove(),这是一个糟糕的答案。而且,如果您查看 ArrayList(以及 AbstractList 和 AbstractCollection)的实现,这对于性能损失来说是一个非常糟糕的答案。
            【解决方案6】:
            while(statsIterator.hasNext()){
              i++;
              PerfStatBean perfBean = statsIterator.next();
              statsIterator.remove();
            

            【讨论】:

            • 你能解释一下为什么这是 O(n^2) 吗?
            • O(n^2):如果要从 ArrayList 中间删除一个元素,则必须复制/移动其余元素。如果您需要经常这样做,请考虑使用 LinkedList。
            • 确实如此。我没有注意到他指定了 ArrayList。
            【解决方案7】:
            ListIterator<PerfStatBean> statsIterator = statFilterResults.iterator();
            while(statsIterator.hasNext()){
              i++;
              PerfStatBean perfBean = statsIterator.next();
              ...
              statsIterator.remove();
            }
            

            【讨论】:

            • @Tom Hawtin 好点,关于 set(null) 而不是删除的好答案。很难猜测 OP 约束是什么。也许 statFilterResults 应该是一个linkedList;也许在循环之后根本不需要它并且 statFilterResults=null 就足够了......
            • 为什么 ArrayList 是 O(n^2)?
            • O(n^2):如果要从 ArrayList 中间删除一个元素,则必须复制/移动其余元素。如果您需要经常这样做,请考虑使用 LinkedList。
            • @Tom:你有什么理由做出这个断言?
            【解决方案8】:

            【讨论】:

            • +1 以获得最佳和明显的答案。 @Tom:实际上,这比将 beansToDelete 放入一个集合并调用 remove all 效率更高,后者为集合中的每个元素调用 contains() 和 remove() 。而且由于迭代器确切地知道元素在列表中的位置,它可以直接将其删除(无需查找)。最后,一个好的列表实现会优化它的迭代器 remove(),或者它的 removeRange() 以利用实现的细节。
            • @Software Monkey:您无法有效地从 ArrayList 中间删除元素(即使您知道位置)。这涉及复制数组的尾部以移动它。
            • @Thilo:是的,但这假设并非所有元素都将被删除,在这种情况下,您无论如何都要承担费用;否则他可以在迭代结束时清除列表。
            猜你喜欢
            • 2018-02-27
            • 1970-01-01
            • 2011-07-07
            • 1970-01-01
            • 1970-01-01
            • 2019-02-03
            • 1970-01-01
            • 2017-05-27
            相关资源
            最近更新 更多