HashMap put 一百万个 kv 都是 Int 类型的数据需要多少空间?
目录
问题
代码实践
实验结果
Java对象内存布局
对象头:
实例数据:
对齐填充:
HashMap本身占用内存
Node占用内存
参考文章
本文内容来源于摘抄总结实践
问题
kv都是 int,一个 int 4 byte,就是100w * 8那就是8M,或者存储的是包装类 Integer ,一个 Integer 16 byte,那就是32 M 咯?
代码实践
通过java.lang.Runtime类中的freeMemory()方法来进行测试,输出freeMemory前,调用一次System.gc(),得出结论是百万键值对的HashMap占用大约69M空间。
package Java2;import java.util.HashMap;/*** @author ranbo* @version V1.0* @Title:* @Package Java2* @Description:* @date 2018/7/26 下午10:55*/
public class HashMapUseMemory {public static void main(String[] args) {double start = 0;double end = 0;System.gc();start = Runtime.getRuntime().freeMemory(); // 在java程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,// 这些挖过来而又没有用上的内存,实际上就是freeMemory()System.out.println("start: " + start);System.out.println("end: " + end);HashMap<Integer, Integer> hashMap = new HashMap<>();for (int i = 0; i < 1000000; i++) {hashMap.put(i, 128); // value 为128 和 127 就是int和Integer的区别,(16 byte - 4 byte) * 100w就是 12 M的样子 IntegerCacheif(i % 10000 == 0) {end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");}}end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");System.out.println("----------清除了没有对象引用的对象"); // 即不可达对象System.gc(); // 清除了没有对象引用的对象,比如里面的临时变量,个人觉得 hash 也是end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");}}}
实验结果
那接下来我们就来分析为啥会有这么多内存占用
Java对象内存布局
Java对象的内存布局包括:对象头(Header),实例数据(Instance Data)和补齐填充(Padding)。
对象头:
64位机器上,默认不开启指针压缩(-XX:-UseCompressedOops)的情况下,对象头占用12bytes,开启指针压缩(-XX:+UseCompressedOops)则占用16bytes。
实例数据:
原生类型(primitive type)的内存占用如下:
Primitive Type |
Memory Required(bytes) |
---|---|
byte, boolean |
1 byte |
short, char |
2 bytes |
int, float |
4 bytes |
long, double |
8 bytes |
对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes。
对齐填充:
Java对象占用空间是8字节对齐的,即所有Java对象占用bytes数必须是8的倍数。例如,一个包含两个属性的对象:int和byte,并不是占用17bytes(12+4+1),而是占用24bytes(对17bytes进行8字节对齐)
HashMap本身占用内存
/*** The table, initialized on first use, and resized as* necessary. When allocated, length is always a power of two.* (We also tolerate length zero in some operations to allow* bootstrapping mechanics that are currently not needed.)*/transient Node<K,V>[] table;/*** Holds cached entrySet(). Note that AbstractMap fields are used* for keySet() and values().*/transient Set<Map.Entry<K,V>> entrySet;/*** The number of key-value mappings contained in this map.*/transient int size;/*** The number of times this HashMap has been structurally modified* Structural modifications are those that change the number of mappings in* the HashMap or otherwise modify its internal structure (e.g.,* rehash). This field is used to make iterators on Collection-views of* the HashMap fail-fast. (See ConcurrentModificationException).*/transient int modCount;/*** The next size value at which to resize (capacity * load factor).** @serial*/// (The javadoc description is true upon serialization.// Additionally, if the table array has not been allocated, this// field holds the initial array capacity, or zero signifying// DEFAULT_INITIAL_CAPACITY.)int threshold;/*** The load factor for the hash table.** @serial*/final float loadFactor;
所以一个HashMap对象本身的大小为:
12(header) + 4(table reference) + 4(entrySet reference) + 4(size) + 4(modCount) + 4(threshold) + 8(loadFactor) + 4(keySet reference) + 4(values reference) = 48(bytes)
接着分析testMap实例在总共占用的内存大小。
Node占用内存
根据上面对HashMap原理的介绍,可知每对键值对对应一个Node对象。根据上面的Node的数据结构,一个Node对象的大小为:
/*** Basic hash bin node, used for most entries. (See below for* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)*/static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}}
12(header) + 4(hash reference) + 4(key reference) + 4(value reference) + 4(next pointer reference) = 28 (padding) -> 32(bytes)
加上Key和Value两个Integer对象,一个Node占用内存总大小为:32 + 2 * 16 = 64(bytes)
100w个就是 1000000 * 64
下面分析HashMap的Node数组的大小。
根据上面HashMap的原理可知,HashMap初为满足100w个node需要扩容到 1024 * 1024 * 2,这样乘以负载因子才会大于100w,所以Node[]占用的内存大小为:
Node[] = 16(header) + 1024 * 1024 * 2 * 4(Node reference) + 1000000 *64(Node)
所以,testMap占用的内存总大小为:
48(map itself) + (16 + (1024 * 1024 * 2 * 4) + 64 * 1000000)(Node[]) = = 72388672 byte
72388672 byte / (1024 *1024) = 69.03521728515625 M
参考文章
一个1000万HashMap,会占用多少空间内存?
Java对象内存占用分析
Java中HashMap结构自身占用的内存和Runtime类的freeMemory()等几个方法
HashMap put 一百万个 kv 都是 Int 类型的数据需要多少空间?相关推荐
- 人工智能数据标注都有哪些类型
人工智能数据标注都有哪些类型 人工智能数据标注指的是,将非结构化数据转换成电脑可以识别理解的结构化数据. 例如,将下图中的车识别出来,人看到车的外轮廓是: 但是需要让电脑去识别认知这个图中的车,电脑需 ...
- 程序员收到阿里offer,提离职被怒:为年薪百万连兄弟都不做啦!
热文推荐: 尘埃落定!清华才子王垠加入华为职级22,前阿里P10赵海平加入字节跳动,职级或为4+ 百度网盘"破解版",Pandownload开发者被抓 在当今社会,钱就是衡量一个人 ...
- 现在Python就业很难吗?百万程序员都在关心的问题
这是我最近逛脉脉职言,看到的一则动态.我知道我们很多已经转行python或者即将转行python都要面对的一个问题–就业! 本文跟大家分享Python的几个主要发展和就业方向,给准备转行学习Pytho ...
- 大数据培训:生活中这些场景都用到了大数据
来源:千锋大数据 一.什么是大数据 大数据(big data),指无法在一定时间范围内用常规软件工具进行捕捉.管理和处理的数据集合,需要新处理模式才能具有更强的决策力.洞察力和流程优化能力的海量.高增 ...
- 在远程调用别人接口的时候,传输参数一般都是String类型的字符串,改字符串可以是json格式的,也可以是xml格式的,那么问题来了
在远程调用接口的时候,传输参数一般都是String类型的字符串,该字符串可以是json规则格式的,也可以是xml规则格式的,那么问题来了. 怎么将自己的对象,拼接成接口规定的格式?即将非格式化的数据( ...
- hive 插入数据映射到hbase_年薪50万都难招的大数据工程师,凭什么?
回顾2018年,降薪.裁员.互联网寒冬似乎成为主旋律,那实际上资本市场萎缩了吗? 其实不然,2018年6月,蚂蚁金服还获得140亿融资,而热度较高的大数据行业,在2018年的融资额达到1273.1亿元 ...
- 元宇宙iwemeta: 重庆打造“数据之都”,拟成立重庆数据交易所
重庆打造"数据之都",拟成立重庆数据交易所.重庆数据交易所,简称重数所. 重庆数据交易所,围绕确权难.定价难.互信难.入场难.监管难等关键共性难题,形成公共性数据资产交易所,提供数 ...
- C++对C的加强之C++中所有的变量和函数都必须有类型
变量和函数都必须有类型 C++中所有的变量和函数都必须有类型 总结 C++中所有的变量和函数都必须有类型 /* C++中所有的变量和函数都必须有类型 C语言中的默认类型在C++中是不合法的 函数f的返 ...
- 计算机d盘给c盘,win10 c盘与d盘都是主分区如何将d盘空间分给c盘
在安装win10系统的时候,用户都喜欢将硬盘分为多个主分区盘符,可是在使用过程中,发现win10系统中c盘空间越来越小,因此就想要将d盘空间分一些给c盘,那么win10系统c盘与d盘都是主分区时如何将 ...
- 有两个集合,两个集合都是10万个数据(已排序),判断B是不是A的子集,算法时间复杂度为Q(N)...
有两个集合 集合A{1,7,19,21,55,100...} 集合B{7,22,100...} 两个集合都是10万个数据(已排序),要求写一个算法,判断B是不是A的子集,算法时间复杂度为 ...
最新文章
- 第三十二课.脉冲神经网络SNN
- awl 多线程SYN***工具0.2版,加了MAC伪装
- 华为AR28-31配置光纤接入
- 从虚拟化、统一映射和自动化看09年法规遵从趋势
- ios - 使用@try、catch捕获异常:
- linux系统硬盘数据恢复软件下载,Linux硬盘数据恢复软件
- Wince6 RIL层移植
- 关于mobile中datagrid的使用
- 解决xampp启动mysql失败
- 1 sqlserver修改表结构
- 入门级XML学习(三)
- python简单的爬虫实例
- 制造车间怎么推行5S管理?
- jdbc常见异常及错误解决办法汇总
- java 实现图片水印 文字水印
- 圆拟合Taubin fit 方法
- matlab7.1一直打不开,Matlab 7.1安装及打不开问题解决
- Java使用aspose批量将PDF转为word
- 气象站可以用计算机分析什么数据,多功能气象站有什么用
- 正确的-配置Tomcat环境变量