目前我正在使用以下数据结构:
MyObject[] arr = new MyObject[100]
现在数组中的大部分字段实际上都是空的(假设 97%)
据我所知,JVM 为每个字段保留了 MyObject
的一个实例所需的内存,因此即使从未真正使用过,也会保留大量内存。
有没有办法节省内存?比如按需只为MyObject
分配空间?
有比简单数组更好的数据结构吗? (需要既高效又快速)
最佳答案
As far as I can see the JVM reserves for each field the requiered memory for one instance of MyObject so a lot of memory is reserved even though it is never really used.
不,它没有。它为 100 个对象引用 保留了足够的内存,而不是 100 个 MyObject
实例。对象引用不大(32 位或 64 位,详见 this answer)。下面是 ASCII 艺术。
现在,如果您对保留 100 个大小为 int
或 long
的插槽感到困扰,您可以使用 ArrayList
它将根据需要重新分配一个支持数组(但这会增加内存碎片),一个 LinkedList
根本不使用数组(但对于它 的条目有更高的内存开销确实有),甚至是像 Map
这样根本(不一定)使用数组的结构(但同样每个条目的开销更高)。
100 位数组的 ASCII 艺术和细节:
所以当你第一次创建那个数组时,这是你在内存中的内容:
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | | null | | null | | (96 more) | | null | +------------+
Then you assign an instance, say:
arr[1] = new MyObject();
这给了你
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | +-------------------+ | reference |---->| MyObject instance | | null | +-------------------+ | (96 more) | | someField | | null | | someOtherField | +------------+ | ... | +-------------------+
...那么也许您可以添加另一个:
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | +-------------------+ | reference |---->| MyObject instance | | reference |--+ +-------------------+ | (96 more) | | | someField | | null | | | someOtherField | +------------+ | | ... | | +-------------------+ | | +-------------------+ +->| MyObject instance | +-------------------+ | someField | | someOtherField | | ... | +-------------------+
...随着您在数组中存储更多实例,依此类推。
关于Java对象数组空元素内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27798592/