哈希映射内存开销

时间:2013-11-24 13:46:11

标签: java memory hashmap

我正在研究Hash Map的内部结构,其中我遇到了以下细节:

  • 实现是一个HashMap $ Entry对象数组:

  • 每个HashMap $ Entry包含:     - int KeyHash     - 下一个对象     - 对象键     - 对象值

  • 默认容量为16个条目

  • 空大小为128字节

  • HashMap的开销是48字节,加上(16 +(条目* 4字节)) array - 加上HashMap $ Entry对象的开销

  • 每个键附加32字节↔值条目HashMap的开销为
    因此: - 48个字节,每个条目加36个字节

任何人都可以解释我“HashMap的开销为48字节,加上(16 +(条目* 4字节))    数组“”每个键附加32字节↔值条目HashMap的开头是
   因此: - 48个字节,每个条目加36个字节“
???

我无法理解这些结论是如何产生的,即我们如何看到关于哈希映射的最终内存细节。

1 个答案:

答案 0 :(得分:2)

You might want to read this SO question.对象开销在不同的CPU架构,VM实现之间以及不同的Java版本之间会有所不同(例如OOPS,还有fixnums的建议等。)

对于OpenJDK 7,HashMap

But let's see for ourselves


  

HashMap

的开销为48字节

家政信息。 大概是8个字节。

实施中有三个字段用于保存keySet()values()entrySet()方法所做的视图。三个指针,即32位机器上的 12个字节

// from AbstractMap
transient volatile Set<K>        keySet = null;
transient volatile Collection<V> values = null;

// from HashMap
private transient Set<Map.Entry<K,V>> entrySet = null

有三个int字段:sizethresholdmodCount 12个字节。

有一个float字段:loadFactor 4个字节。

表指针本身(Entry[] table)。 4个字节。

static final字段不计算,它们是编译时常量)

所有这些都为我们提供了 40字节 HashMap实例的固定成本。它不是48字节,我不知道为什么。也许我错过了一些东西,也许你的文字提到了其他版本。这些事情有时会有所改变。过去可能有一个额外的领域。也许它填充了40到48个字节(但它不应该)。


  

16 +(条目* 4字节)数组

构造Entry[] tableHashMap表被实例化,我们也需要计算它。

实例化数组需要 8个字节的内务数据,4 bytes属性length。那是 12个字节,而不是16.再次,不知道它来自哪里。

每个条目都是指向Entry对象的指针,因此每个条目的 4个字节。这很容易。


  

每个键增加32个字节↔值条目

再次, 8字节的管家。

现在,字段:

final K key;    // a reference, 4 bytes
V value;        // a reference, 4 bytes
Entry<K,V> next;  // a reference, 4 bytes
final int hash; // an integer primitive, 4 bytes

16个字节。

每个条目的最终计数 24个字节。再说一遍,那不是36。


我不知道你在那里得到的数字来自哪里。那可能是IBM虚拟机吗?这可能是64位操作系统吗?也许家政信息现在是16字节(Java 8会改变什么吗?)。

无论如何,我试着根据我的最佳知识来计算内存消耗。