【问题标题】:Java clearing a list by creating a new instanceJava 通过创建新实例来清除列表
【发布时间】:2011-08-31 13:36:09
【问题描述】:

我正在查看 Java 代码,发现了这段代码:

list = new ArrayList();
uselist(list);

if (condition)
   list = new ArrayList();

这个有什么用,而不是简单地使用 ArrayLists 的 clear() 方法。

使用新命令清除列表没问题,是否比清除列表更快?

我使用的是 java 1.6 版

【问题讨论】:

    标签: java performance list arraylist new-operator


    【解决方案1】:

    请注意,清除和重新实例化列表不是一回事!

    考虑这个例子:

    a = new ArrayList();
    a.add("Hello")
    b = a;
    a = new ArrayList();   // a is now empty while b contains hello!
    

    对比

    a = new ArrayList();
    a.add("Hello")
    b = a;
    a.clear();            // Both a and b are now empty.
    

    如果副作用(共享引用)不是问题,那么这只是清除列表的两种方法。除非这被调用了数百万次,否则它可能不应该是性能问题。

    【讨论】:

    • 如果它被调用百万次,哪个会更快?
    • 我不知道。当面对这样的潜在优化时,我可能不得不对其进行基准测试。它可能在很大程度上取决于诸如列表大小之类的情况,在 clear() 之后保留 ArrayList 的(更大)内部数组是否会对应用程序的性能产生负面影响等。我确实怀疑这些差异很少引起注意,并且几乎可以肯定,无论哪种方式,这都是一种不必要的优化。
    【解决方案2】:

    不,他们不做同样的事情。 clear() 方法清除 现有 列表 - 任何仍然引用该列表并稍后查看它的内容都会发现它是空的。

    使用 new 关键字的方法会更改 list 变量的值,但不会对现有的 ArrayList object 做任何事情 - 所以如果有其他东西有引用同一个对象,他们不会看到任何变化。

    【讨论】:

      【解决方案3】:

      如果在其他地方使用该列表,调用clear() 可能会产生副作用。 但是,如果不是这种情况,我会说创建一个新列表而不是清除旧列表可能会更快(但是,可能仅适用于大型列表,因为 ArrayList 的 @ 987654323@ 只是迭代元素并将它们设置为null),但很可能这只是编程风格的问题。

      【讨论】:

      • 我对副作用有完全相反的经验。当列表通过代理连接到休眠时,新的运算符导致休眠翻转。
      • @Farmor 是的,事实上这两种方法都可能会导致副作用,但假设这里没有使用 Hibernate 和类似的使用库的反射,new 可能会导致更少的副作用(意味着列表可能仍然在其他地方使用可能会“突然”为空)。
      • 它会导致 Hibernate 出现问题,因为 Hibernate(以及大多数其他 JPA 实现)将您的 List 替换为另一个由 Hibernate 创建和管理的实例,以便它可以跟踪修改和加载元素懒惰地列出它们,而不是预先加载所有内容。在这种情况下,由于列表在您和 hibernate 之间共享,因此您必须调用 .clear() 并具有告诉 Hibernate 您实际上正在删除这些元素的积极副作用。
      • @Simone 是的。在 Hibernate 的情况下,你会有一个代理列表,但是,我假设这里没有使用 Hibernate。
      • 不不,这里从未提到过 Hibernate,我只是在推测它:D
      【解决方案4】:

      是否相同取决于 uselist(...) 在内部对列表执行的操作。

      例如,假设您在 uselist 中有以下代码:

      public void uselist(List l) {
          this.mylist = l;
      }
      

      在这种情况下,您的代码将创建一个新列表,而不是触及 this.mylist 。相反,如果您在其上调用 .clear(),则您正在清除相同的列表。

      【讨论】:

        【解决方案5】:

        这种差异可能是致命的,而且很难看出。例如hibernate 将翻转你使用list = new ArrayList();然后尝试更新数据库中的列表,但它可以正常使用 clear() 作为休眠然后可以看到连接。

        clear() // operates on your old object 
        
        list = new ArrayList(); // list will be a new object the old will be GCed
        

        【讨论】:

          猜你喜欢
          • 2016-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多