Java 重新实例化列表或调用clear()的更好实践
使用Java(1.6)对列表调用clear()方法更好,还是只是重新实例化引用 我有一个ArrayList,其中填充了未知数量的对象,并定期“刷新”——处理对象并清除列表。刷新后,列表将再次填充。冲洗在随机时间进行。列表中的数字可能较小(10个对象)或较大(数百万个对象) 那么,使用“flush”调用clear()还是新的ArrayList()更好呢 这类问题值得担心吗?还是应该让虚拟机来担心?我怎样才能通过查看Java的内存占用来解决这类问题呢Java 重新实例化列表或调用clear()的更好实践,java,list,Java,List,使用Java(1.6)对列表调用clear()方法更好,还是只是重新实例化引用 我有一个ArrayList,其中填充了未知数量的对象,并定期“刷新”——处理对象并清除列表。刷新后,列表将再次填充。冲洗在随机时间进行。列表中的数字可能较小(10个对象)或较大(数百万个对象) 那么,使用“flush”调用clear()还是新的ArrayList()更好呢 这类问题值得担心吗?还是应该让虚拟机来担心?我怎样才能通过查看Java的内存占用来解决这类问题呢 非常感谢您的帮助。需要关注的主要问题是,还有哪些
非常感谢您的帮助。需要关注的主要问题是,还有哪些代码可能引用了该列表。如果现有列表在别处可见,您希望该代码看到已清除的列表,还是保留现有列表 如果没有其他人可以看到这个列表,我可能会清除它——但不是出于性能原因;只是因为您描述操作的方式听起来更像是清除,而不是“创建一个新列表”
ArrayList
文档没有指定底层数据结构会发生什么情况,但是看看Eclipse中的1.7实现,您可能应该在clear()
之后调用trimToSize()
——否则您仍然可以拥有一个由大量空引用支持的列表。(当然,这对您来说可能不是问题……也许这比在阵列大小再次增大时复制阵列更有效。您将比我们了解更多。)
(当然,创建新列表并不需要旧列表将所有数组元素设置为null……但我怀疑这在大多数情况下是否有意义。)我认为如果Arraylist被频繁刷新,例如,如果它是在循环中连续运行的,或者更好地使用clear,如果刷新不太频繁,那么您可以创建一个新实例。此外,由于您说元素可能从10个对象到数百万个不等,您可以为您创建的每个新Arraylist选择介于两者之间的大小,以便Arraylist可以避免大量调整大小时间 您使用它的方式与a的使用方式非常相似。当您处理队列中的项目时,它们将在您处理它们时被删除 使用其中一个队列类可能会使代码更加优雅
还有一些变体可以以可预测的方式处理并发更新。list.clear()与new XXList相比没有任何优势。 这里是我的调查,以比较性能
import java.util.ArrayList;
import java.util.List;
public class ClearList {
public static void testClear(int m, int n) {
List<Integer> list = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
list.add(Integer.parseInt("" + j + i));
}
list.clear();
}
System.out.println(System.currentTimeMillis() - start);
}
public static void testNewInit(int m, int n) {
List<Integer> list = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
list.add(Integer.parseInt("" + j + i));
}
list = new ArrayList<>();
}
System.out.println(System.currentTimeMillis() - start);
}
public static void main(String[] args) {
System.out.println("clear ArrayList:");
testClear(991000, 100);
System.out.println("new ArrayList:");
testNewInit(991000, 100);
}
}
/*--*
* Out:
*
* clear ArrayList:
* 8391
* new ArrayList:
* 6871
*/
import java.util.ArrayList;
导入java.util.List;
公共类清除列表{
公共静态void testClear(int m,int n){
列表=新的ArrayList();
长启动=System.currentTimeMillis();
for(int i=0;i
可见性不是问题。我喜欢你对清晰方法的推理,因为它有助于描述正在发生的事情。我以前从未见过trimToSize()-我也会检查一下,你是说“1.7实现”吗?当然Eclipse不支持Java1.7(因为它还没有推出),或者我误解了它。@Phil:我使用的是Build1.7.0-ea-b78。它是这个系统上唯一的JVM。尽管它还没有发布,但已经有很多年的版本了,Eclipse在它上面运行,我没有看到任何问题。我想知道:我过去常常清除列表,然后将其设置为null——但这只是因为我不完全确定如果直接将列表设置为null会发生什么(该列表中的所有元素是否都自动设置为null?),而不首先清除它。我想确保没有任何列表元素保持“挂起”@Zainodis:这完全取决于是否有其他对同一对象的引用。但是你当然不需要清除列表或将变量设置为null,前提是该变量没有在其他地方使用。将变量设置为null对列表没有任何作用-它只是一个变量。别忘了,可能还有其他对列表的引用相同的列表。请注意Jon关于优化部分的回答-如果您处理的是高强度,并且存在缓慢性,那么请对其进行分析。如果问题很明显,那么您可以轻松测试将其更改为创建一个新列表。但是,否则,请使用语义上最正确的内容-即代码实际尝试的内容是否与绩效相关: