Java:清除集合的最佳样式

Java:清除集合的最佳样式,java,Java,假设我有一种垃圾收集语言,比如Java for (...) { List <String> lst = new ... // do something with lst // lst not longer needed for this pass of the loop lst.clear (); } 不需要在环体末端进行清除。lst将在下一个关卡中重新启动。内存也将被GC释放 但是,做清除还是跳过它更好呢?我认为可以公平地说:将调用添加到清除是一种不好的做

假设我有一种垃圾收集语言,比如Java

for (...)
{
  List <String> lst = new ...
  // do something with lst
  // lst not longer needed for this pass of the loop

  lst.clear ();   
}
不需要在环体末端进行清除。lst将在下一个关卡中重新启动。内存也将被GC释放


但是,做清除还是跳过它更好呢?

我认为可以公平地说:将调用添加到清除是一种不好的做法

这很简单:您努力以您能想到的最具表现力的方式编写尽可能少的代码来完成您所需要的工作

因此:你要避免放下任何毫无意义的东西

对于一个后来没有使用的集合,一个明确的定义就是:没有意义。除了在运行时对性能产生影响外,它还可能很容易让读者感到困惑!见鬼,他在清理那东西,为什么


编程中的第一条规则:不要编写让读者感到惊讶的代码

在这种情况下,一般的建议是——跳过它,除非你真的对此有问题:通过分析器验证

请注意,只要列表本身还活着,列表中的任何内容都会一直活着;因为它是强引用它的条目

您展示的是一个方法范围的列表,这是一个完全不同的故事,在这种情况下调用ArrayList::clean在大多数情况下对我来说都是无用的


您还应该了解,本地方法列表仍然可以被GC编辑,可访问性和范围是不同的

不要在循环结束时调用list.clear,因为如果它是在循环内部创建的,那么在该迭代之后它将死亡。在方法或块内部创建的对象是年轻的,它们将立即有资格进行垃圾收集。如果调用list.clear方法,将增加代码的开销和不必要的复杂性。

我使用WeakReference队列跟踪硬引用,并观察它们何时被gc删除

我发现gc元素列表的最快方法是给它赋值null并调用垃圾收集器。对于在方法或块中创建的列表来说,这似乎是正确的,并且立即发生。不做这两个,等待方法没有完成。我只给了它几分钟,如果你担心耗尽的堆空间,你可能会考虑软引用。< /P> 有趣的旁注:当我使用整数而不是字符串时,我创建了从0到N_元素的整数对象。除了低128个外,所有的垃圾都被收集了。我认为这是因为根据Java规范,0到127之间的整数值是内部的,所以硬引用仍然存在

导入java.lang.ref.*; 导入java.util.*; 公共类GCT测试{ ReferenceQueue rq=新的ReferenceQueue; List wkrefs=新建阵列列表; 静态int N_元素=1_000_000; 公共静态无效字符串[]args{ 新GCTest.start; } 公共无效启动{ List hardRefStrings=newarraylist; 对于int j=0;ja==null.count; 如果lastcount!=计数{ lastcount=计数; } } System.out.printlnDone; } }
您是否尝试过对这两种方法进行基准测试?我们只考虑字符串列表,而不是其他地方可能引用的内容列表?不。我要求的是样式、性能,而不是太多。我认为风格在大多数情况下比性能更重要。@chris01,如果你在寻找风格,那就清除它吧。此外,如果for循环结束,最后一个列表将被清除,然后。。。编辑:我的坏消息列表在范围内,所以不需要纯粹为了样式而清除它:不要清除它。同时考虑性能:不要清除它所有的数据都变得不可访问,所以您只需花费时间将其设置为null。只有当列表在for循环的范围内时才是这样。如果要在for循环之后清除列表,请在循环外部重新设置列表。那就最好把它清理干净。这样,你就不会在你的清单上有上一次的任何剩余loop@DigitalJedi不过,这是个问题。如果列表存在于更广泛的范围内,则清除与否将成为一个正确性问题,这是一个根本不同的问题。您将范围与可达性混淆这是一个很好的答案,IMO,1+。我不会使用String v=new Stringabcdefg;,而是一个简单的新对象。还包括System.gc;这并不意味着将触发GC,而是
毕竟,这只是一个暗示。还请注意,清除WeakReference是一个异步过程,在GC和将该事件发布到ReferenceQueue之后有一个时间段。我认为它们最终会被GC处理,但由于一些我无法解释的原因,将null分配给列表并调用GC显然加快了过程。这是在Windows 10上。加快进程是什么意思?等待循环立即完成,而不是继续运行。正如我所说,我只花了几分钟。但是关于给list对象赋值null和调用gc的一些事情产生了一些我无法解释的效果。。。但无论如何,没有明确的时间框架记录在任何地方,所以它取决于GC,Env,月球的相位等。。。