ArrayList vs HashSet,哪个更好的内存性能?

时间:2016-06-08 14:27:36

标签: java memory arraylist collections hashset

在以下测试中:

public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("start 1: " + new Date());
                Collection collection = new ArrayList();
                for (int i = 0; i < 1000 * 1000 * 1000; i++) {
                    collection.add(new Object());
                }
                System.out.println("middle 1: " + new Date());
                Iterator iterator = collection.iterator();
                while (iterator.hasNext()) {
                    iterator.next().toString();
                }
                System.out.println("\nend 1: " + new Date());
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("start 2: " + new Date());
                Collection collection = new HashSet();
                for (int i = 0; i < 1000 * 1000 * 1000; i++) {
                    collection.add(new Object());
                }
                System.out.println("middle 2: " + new Date());
                Iterator iterator = collection.iterator();
                while (iterator.hasNext()) {
                    iterator.next().toString();
                }
                System.out.println("\nend 2: " + new Date());
            }
        });
        t1.start();
        t2.start();
    }

我得到了一个关于ArrayList方法的OutOfMemory。

但是,on this high voted answer,它说HashSet消耗更多内存。 答案中断开的链接看起来像是this one

我的测试有问题吗?或者,ArrayLists的内存使用率确实比HashSet差?

- 更新:实际上,通过使用collection.add(&#34;。&#34;);我从arrayList获取outOfMemory。但是对于collection.add(new Object());我得到了两个。

2 个答案:

答案 0 :(得分:1)

当您想要测量Heap中对象的大小时,一种好的方法是使用优秀的工具SizeOf,它可以让您获得对象的深度大小,这要归功于{{ 1}}。

所以这里举例来说SizeOf.deepSizeOf只有只有 10百万个对象实例(实际上我没有像你的例子那样拿10亿)需要ArrayList,如果我设置得当大小为10百万(感谢205 Mo),它将大小缩小为new ArrayList(size)。如果190 Mo无论我设置的是什么大小,都需要HashSet,所以它会超过两倍。

NB:我在521 Mo启用了64-Bit JVM的情况下获得了这些结果。

请注意,大小取决于目标JVM,如果目标JVM是UseCompressedOops32-bit JVM 64-bit JVM(-XX:+ UseCompressedOops),结果确实会改变)默认情况下启用的情况是小于UseCompressedOops的堆或禁用32 GB的{​​{1}}(-XX:-UseCompressedOops)。

答案 1 :(得分:0)

消耗更多内存的Hashsets是有意义的,因为他们需要为潜在的散列值(存储桶)设置空间。现在我不知道它是否消耗了5.5倍的内存(当然这取决于你所存储的对象的性质)但是想到这样的话。 Hashsets是Hashtables,因为arraylists是数组。你将在hashsets中有一些空的空间,这就是消耗额外内存的地方,但对于你正在进行的10亿次迭代,它可能是值得的