【发布时间】:2011-12-21 06:36:59
【问题描述】:
Java 专家强调避免过早优化的重要性,而是专注于干净的 OO 设计。我试图在重写使用大量长元素(几百万)的程序的上下文中协调这一原则。似乎使用 ArrayList 会消耗大约 3 倍于原始 long 数组的内存,而且浪费这么多 RAM 对我来说似乎是一个合理的担忧。
这是基于我使用 MemoryTestBench 类 described here 进行的实验。我的测试和输出如下:
package memory;
import java.util.ArrayList;
import java.util.List;
public class ArrayListExperiment {
public static void main(String[] args) {
ObjectFactory arrayList = new ObjectFactory() {
public Object makeObject() {
List<Long> temp = new ArrayList<Long>(1000);
for (long i=0; i<1000; i++)
temp.add(i);
return temp;
}
};
ObjectFactory primitiveArray = new ObjectFactory() {
public Object makeObject() {
long[] temp = new long[1000];
for (int i=0; i<1000; i++)
temp[i] = i;
return temp;
}
};
MemoryTestBench memoryTester = new MemoryTestBench();
memoryTester.showMemoryUsage(primitiveArray);
memoryTester.showMemoryUsage(arrayList);
}
}
和输出:
memory.ArrayListExperiment$2 produced [J which took 8016 bytes
memory.ArrayListExperiment$1 produced java.util.ArrayList which took 24968 bytes
我的问题是:我怎样才能获得 OO 列表的好处,同时仍然保留原始数组的小内存占用?我认为 guava 可能会提供答案,但是通过 API 浏览一下,我不清楚使用哪个类代替 ArrayList。
感谢您的任何建议。
【问题讨论】:
-
这个 MemoryTestBranch 是否正确?看了文章没多久,看到了 System.gc() 之类的一些有趣的方法,一个接一个地看了几次。
-
实际上,这听起来很对。 Double 需要一个参考,加上实际的原始双精度。在 64 位 JVM 中,您至少需要为 Double 支付两倍于 double 的成本,而且还有一些额外的开销。
-
rit,我没有资格评论那篇文章中方法的清洁度,但我相信内存结果是正确的
-
你想做什么? ArrayList 总是会花费更多,因为它只包含对象(在您的情况下为 Double)。由于每个 Object/Double 确实是一个引用,因此每个 Double vs double 都会花费您额外的内存空间。 (在您的情况下为 1000)(参考 + 双精度的实际值)。
-
为 Java 应用程序提供 1 GB 内存的情况并不少见。列表中有 300 万
Doubles:~ 0.07 GB。似乎内存占用很小:-)
标签: java data-structures guava