Java 中一个保存了 1 万个整数的 ArrayList 占多少内存? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
61162833
V2EX    Java

Java 中一个保存了 1 万个整数的 ArrayList 占多少内存?

  •  
  •   61162833 2023-11-12 10:59:52 +08:00 5208 次点击
    这是一个创建于 698 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码:
    List<Integer> ints=new ArrayList();
    for(int i=0;i<10000;i++){
    ints.add(i);
    }

    gpt-3.5 的回答:
    在 64 位的 Java 虚拟机中,一个空的 ArrayList 对象通常占用 24 字节。
    在 Java 中,一个 Integer 对象通常占用 16 字节(在 32 位和 64 位的 Java 虚拟中都是如此)。

    在 64 位的 Java 虚拟机中:
    ArrayList 对象本身:24 字节
    整数对象:16 字节 × 10000 = 160000 字节
    总内存占用:24 字节 + 160000 字节 = 160024 字节

    也就是说,一个仅保存了 1 万个整数的 ArrayList 就要占 160KB 服务器内存?
    一个保存了 10 万个整数的 ArrayList 就要占 1.6MB 内存?

    怎么与实际感觉似乎不太相符,
    有能用 gpt 4.0 的富哥问下这答案对吗?

    另外,ArrayList 中保存的整数占内存数与数字大小有关系吗?(比如保存 1 万个 1 亿+的数字,与保存 1-10000 有区别吗?)
    16 条回复    2023-11-13 11:19:37 +08:00
    cubecube
        1
    cubecube  
       2023-11-12 11:20:20 +08:00   1
    gpt 回答是正确的
    和数字大小没关系,int 最大 21 亿
    yfugibr
        2
    yfugibr  
       2023-11-12 11:24:28 +08:00 via Android   1
    不止,ArrayList 的空间分配不是要多少就分配多少,而是在容量填满后扩充到之前的大约 1.5 倍(可以去看具体实现),你存 a 个对象,但它分配的空间可能多达 1.5a 个
    61162833
        3
    61162833  
    OP
       2023-11-12 11:25:23 +08:00
    @cubecube 谢谢,这么一算感觉内存很不经用啊,保存几十万个数字就要爆了
    61162833
        4
    61162833  
    OP
       2023-11-12 11:26:22 +08:00
    @yfugibr 就是保存 100 个数字要占 150 个数字的内存空间?
    rabbbit
        5
    rabbbit  
       2023-11-12 11:27:57 +08:00   1
    ArrayList 可以设定初始容量值,避免自动扩容。
    int 占 4 字节
    嫌多还有 short 2 字节 byte 1 字节
    humpy
        6
    humpy  
       2023-11-12 11:32:11 +08:00   4
    可以用 [JOL]( https://github.com/openjdk/jol) 工具测一下:

    System.out.println(GraphLayout.parseInstance(ints).toFootprint());

    --

    java.util.ArrayList@5679c6c6d footprint:
    COUNT AVG SUM DESCRIPTION
    1 40016 40016 [Ljava.lang.Object;
    10000 16 160000 java.lang.Integer
    1 24 24 java.util.ArrayList
    10002 200040 (total)

    在我的机器上( 64 位 JDK8 ),大约 200040 / 1024 = 195kb
    yeqizhang
        7
    yeqizhang  
       2023-11-12 11:33:07 +08:00 via Android   1
    没啥不相符合的,首先高并发的项目,出现大集合的情况少,其次集群下,单台机的业务并发也不会太高,有高并发的业务都堆机器堆内存去了。
    还有就是,只要变成垃圾变的快,jvm 回收了也没啥压力。
    yfugibr
        8
    yfugibr  
       2023-11-12 11:33:51 +08:00   1
    @61162833 #4 不是这个意思,ArrayList 底层存储是数组,有一个初始容量(不确定是多少),会在数组被填满时建一个新数组替换旧数组来扩充容量,新数组的容量大约是之前的 1.5 倍(取决于具体实现),直到新数组再次被填满时再次扩容,所以多数情况下都是有空间“浪费”的,但是浪费了多少要看你的存入的容量和 ArrayList 的实现。

    当然你也可以直接指定 ArrayList 的容量,这部分就自行搜索吧。
    mazyi
        9
    mazyi  
    PRO
       2023-11-12 12:32:58 +08:00 via iPhone
    这有啥不经用的,你可以去看看 python 的,和 js 的,让你对编程语言有全新认识
    ruxuan1306
        10
    ruxuan1306  
       2023-11-12 12:35:52 +08:00
    @yfugibr 自动扩容是在 append 时原容量不够才发生的,new 时候给定大小,然后直接用下标设置就不会触发扩容。
    winglight2016
        11
    winglight2016  
       2023-11-12 13:23:28 +08:00
    lz 如果觉得内存很容易不够用,可以去看看微机原理这本书,或者了解一下 linux 内核的内存寻址相关内容。

    jvm32 位的时候,最大内存只有 1.5G ,的确很容易爆,但是 64 位已经支持到超过硬盘容量了,更大数量的并行计算(如果不需要并行,那限制只是时间问题)已经转变成了分布式计算的问题,而不是高效利用内存这和 AI 的发展趋势相似,注意力放在了解决通用问题。
    junkun
        12
    junkun  
       2023-11-12 14:31:58 +08:00   1
    补充一下,如果要省内存可以用 int[]数组,或者自己用数组封装一个 int 类型的线性表。主要是因为 Java 泛型只能支持封装类型的元素,所以占用空间不理想。然而基本类型的数组除了头以外,内部是连续存储的。
        13
    lancelee01  
       2023-11-13 10:30:58 +08:00
    10 万个整数,1.6MB 说实话不大啊。再优化也就是把 List 改成数组,数组本身占用 16 字节,节省 8 字节,整数 int 4 字节,累计 16 + 4 * 100000 ,相当于减少一半
    zhouhu
        14
    zhouhu  
       2023-11-13 11:14:10 +08:00
    @junkun 是的,很多开源的集合库可以用。比如 eclipse collection 。
    Aresxue
        15
    Aresxue  
       2023-11-13 11:17:24 +08:00
    所以有了 fastutil 这个库。。话说 java 自己的 Valhalla 项目正在做泛型特化以后你就可以用 List<int>了。
    zhouhu
        16
    zhouhu  
       2023-11-13 11:19:37 +08:00
    还可以开启指针压缩
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     923 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 22:15 PVG 06:15 LAX 15:15 JFK 18:15
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86