Java LinkedHashSet与哈希集内存消耗

Java LinkedHashSet与哈希集内存消耗,java,Java,在Java中,LinkedHashSet比“普通”哈希集消耗多少内存(字节)? 我知道LinkedHashSet对于某些操作来说稍微慢一点,但是内存使用情况如何呢?顾名思义,文档明确表示,除了核心之外,还需要维护一个链接列表。我认为在这里可以安全地假设,内存消耗的上限可以近似为两个独立的数据结构:散列集和链表。它们消耗了多少内存,这是另一个问题 但是,如果您需要有关所用内存字节数的硬数据,您可以自己执行一些测试。测试应该不会太难,或者谷歌暂时也不会太难——我相信互联网上已经有了一些测试结果 @编

在Java中,LinkedHashSet比“普通”哈希集消耗多少内存(字节)?
我知道LinkedHashSet对于某些操作来说稍微慢一点,但是内存使用情况如何呢?

顾名思义,文档明确表示,除了核心之外,还需要维护一个链接列表。我认为在这里可以安全地假设,内存消耗的上限可以近似为两个独立的数据结构:散列集和链表。它们消耗了多少内存,这是另一个问题

但是,如果您需要有关所用内存字节数的硬数据,您可以自己执行一些测试。测试应该不会太难,或者谷歌暂时也不会太难——我相信互联网上已经有了一些测试结果

@编辑,在路易斯的回答之后

我觉得很有意思,为什么差别更小。我写了一个简单的基准测试:

package com.company;

import com.javamex.classmexer.MemoryUtil;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Random;

public class Main
{
    public static void main(String[] args)
    {
        // Creating data structures under test -------
        HashSet<Integer> hashSet = new HashSet<>();

        Random random = new Random();
        for (int i=0; i<1000000; i++)
        {
            hashSet.add(random.nextInt());
        }

        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>(hashSet);

        // Measuring memory usage --------------------
        long sizeOfHashSet = MemoryUtil.deepMemoryUsageOf(hashSet);
        long sizeOfLinkedHashSet = MemoryUtil.deepMemoryUsageOf(linkedHashSet);
        System.out.println("Size of HashSet:\n" + sizeOfHashSet + " B");
        System.out.println("Size of LinkedHashSet:\n" + sizeOfLinkedHashSet + " B");
        System.out.println("LinkedHashSet is bigger from HashSet by " + (sizeOfLinkedHashSet*100/sizeOfHashSet - 100) + "%");

        System.out.println("\n");

        long numberOfElements = hashSet.size();
        System.out.println("Number of elements in the test HashSet: " + numberOfElements);

        System.out.println("Average size of a single element in HashSet: " + sizeOfHashSet/numberOfElements + " B");
        System.out.println("Average size of a single element in LinkedHashSet: " + sizeOfLinkedHashSet/numberOfElements + " B");
    }
}

有趣的是,它与路易斯给出的值不一致。但是,每个元素的字节数差异与Louis编写的(8b)相同。有人能解释一下价值观上的差异吗?我是否以错误的方式测量对象大小?

顾名思义,文档明确指出,除了核心之外,还需要维护一个链接列表。我认为在这里可以安全地假设,内存消耗的上限可以近似为两个独立的数据结构:散列集和链表。它们消耗了多少内存,这是另一个问题

但是,如果您需要有关所用内存字节数的硬数据,您可以自己执行一些测试。测试应该不会太难,或者谷歌暂时也不会太难——我相信互联网上已经有了一些测试结果

@编辑,在路易斯的回答之后

我觉得很有意思,为什么差别更小。我写了一个简单的基准测试:

package com.company;

import com.javamex.classmexer.MemoryUtil;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Random;

public class Main
{
    public static void main(String[] args)
    {
        // Creating data structures under test -------
        HashSet<Integer> hashSet = new HashSet<>();

        Random random = new Random();
        for (int i=0; i<1000000; i++)
        {
            hashSet.add(random.nextInt());
        }

        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>(hashSet);

        // Measuring memory usage --------------------
        long sizeOfHashSet = MemoryUtil.deepMemoryUsageOf(hashSet);
        long sizeOfLinkedHashSet = MemoryUtil.deepMemoryUsageOf(linkedHashSet);
        System.out.println("Size of HashSet:\n" + sizeOfHashSet + " B");
        System.out.println("Size of LinkedHashSet:\n" + sizeOfLinkedHashSet + " B");
        System.out.println("LinkedHashSet is bigger from HashSet by " + (sizeOfLinkedHashSet*100/sizeOfHashSet - 100) + "%");

        System.out.println("\n");

        long numberOfElements = hashSet.size();
        System.out.println("Number of elements in the test HashSet: " + numberOfElements);

        System.out.println("Average size of a single element in HashSet: " + sizeOfHashSet/numberOfElements + " B");
        System.out.println("Average size of a single element in LinkedHashSet: " + sizeOfLinkedHashSet/numberOfElements + " B");
    }
}
有趣的是,它与路易斯给出的值不一致。但是,每个元素的字节数差异与Louis编写的(8b)相同。有人能解释一下价值观上的差异吗?我测量对象大小的方法是否错误?

一个
HashSet
是~32字节/元素;一个
LinkedHashSet
是大约40字节/元素。


一个
HashSet
是~32字节/元素;一个
LinkedHashSet
是~40字节/元素。

在那里看不到重复@Bruno_Ferrei可能需要几个指针和列表头。你查过实现源代码了吗?没有在那里看到dupe@Bruno_ferrei可能需要几个指针和列表头。您是否检查了上的实现源代码?
HashSet
是32字节/元素
LinkedList
是24字节/元素,
LinkedHashSet
是40字节/元素。在32位JVM和64位JVM中运行时,无论是否启用
CompressedOops
等等,都会有不同
LinkedList
是24字节/元素,
LinkedHashSet
是40字节/元素。它们不仅仅是添加。在32位JVM和64位JVM中运行可能会有所不同,有或没有启用
CompressedOops
等等。对于64位JDK,这可能是假设
CompressedOops
处于活动状态,但至少在热点上达到>32GB堆之前应该是这样。你肯定应该使用它,所以是的,对于大多数情况,这应该是最现实的数字。是的,默认情况下它是打开的,所以大多数人都在使用它,不管他们是否知道它。可能关心链接节点的内存使用的人正在使用一个巨大的堆。对于64位JDK,这可能是假设
CompressedOops
处于活动状态,但至少在热点上达到>32GB的堆之前应该是这样。你肯定应该使用它,所以是的,对于大多数情况,这应该是最现实的数字。是的,默认情况下它是打开的,所以大多数人都在使用它,不管他们是否知道它。不过,有可能关心链接节点的内存使用的人正在使用一个巨大的堆。