动态增长阵列的Java连续内存分配?

动态增长阵列的Java连续内存分配?,java,memory-management,jvm,dynamic-arrays,Java,Memory Management,Jvm,Dynamic Arrays,我试图用java实现一个面向列的数据存储引擎。我想知道是否有其他方法可以实现动态增长阵列的连续内存分配 HashMaps无法在扩展/调整大小时分配连续内存块 即使创建更大的新固定数组并将值从旧固定数组复制到此新数组,看起来也是实现连续性的唯一选项,但与例如相比,这是非常缓慢的。假设列中已有100万条记录(固定数组)当前大小为100万,您需要在1000001位置插入新值,然后jvm必须创建大小为1000001的新数组,并将所有值复制到大小更大的新数组(仅插入一个值),并保持连续性 ArrayLis

我试图用java实现一个面向列的数据存储引擎。我想知道是否有其他方法可以实现动态增长阵列的连续内存分配

HashMaps无法在扩展/调整大小时分配连续内存块


即使创建更大的新固定数组并将值从旧固定数组复制到此新数组,看起来也是实现连续性的唯一选项,但与例如相比,这是非常缓慢的。假设列中已有100万条记录(固定数组)当前大小为100万,您需要在1000001位置插入新值,然后jvm必须创建大小为1000001的新数组,并将所有值复制到大小更大的新数组(仅插入一个值),并保持连续性


ArrayList在内部的工作方式与上述相同(分配新数组+复制旧值等等)。因此,对于线程安全来说,向量具有额外的同步开销


因此,另一种通过在初始化过程中创建一个巨大的固定数组来分配大型连续内存的方法会导致大量未使用的内存,这不是一个可行的解决方案


如果有更好的选择,请提供帮助。例如,(如果可以在Java中实现)知道当前固定数组中最后一个元素的地址,并以某种方式检查下一个连续的可用块是否可用?如果是这样的话,那么使用它来存储新的值以及更新数组索引以适应这个新的更改以保持O(1)时间读取访问



谢谢。

有很多黑客攻击,但是Java的
ArrayList
是现有阵列组合中最有效的一种,可以扩展

您可以创建具有固定长度的数组,然后将它们连接到列表中(因此,增长只需要附加一个额外的数组,而不需要复制它)。但是,如果您的数据结构预计会有很大的增长,那么最好将其完全实现为一个列表

您可以通过将连接的数组的大小加倍来扩展此功能。因此,您可以创建一个数组列表,其大小分别为
50、100、200、400
,依此类推。可以按如下方式计算阵列(和位置):

int x = 55; // position

int position = (int)Math.floor(Math.log(1 + x / 50) / Math.log(2));
int arrayposition = x - (Math.pow(2, position) * 50);

即使对于大数据值,这仍然是一个非常快速的数据结构(
O(n)
是数据检索的最坏情况,扩展它是
O(1)

如果您试图“手动”执行此操作,一种常见的技术是每次需要增加数组时将其大小增加一倍。因此,在您的示例中,您可以将数组大小调整为200万;这是昂贵的,但这意味着你将不需要重新调整了很长一段时间


这使您可以在摊销的固定时间内插入数组,尽管有时可能不需要像复制100万行这样昂贵的操作,因此您可能需要修改此想法以适应您的特定需要。有关动态阵列实现的更多讨论,请参阅。

好吧,这些基本上是您的选择:首先分配大量内存,并且知道您不必进行复制,但同时会“浪费”内存,或者根据需要分配较小的块并进行复制。大小合理的块的链接列表是一个“中间地带”。为什么连续的内存对你很重要?此外,ArrayList由一个数组和连续内存支持。当然,您可以手动执行与
ArrayList
相同的操作(并避免在此过程中进行装箱),其实没那么难。我只是检查了ArrayList的jdk内部实现,了解到internal它是用默认大小10初始化的,然后执行相同的过程,创建新的数组+1大小,然后->在需要扩展add()方法时将旧值复制到此新值。所以我认为它们是用连续的内存块(由数组索引支持)分配的,但在重新调整巨大的arraylist的大小时,性能会受到影响?例如,知道当前固定数组中最后一个元素的地址,并以某种方式检查下一个连续的可用块是否可用?如果是这样的话,那么使用它来存储新的值以及更新数组索引以适应这个新的更改以保持O(1)时间读取访问?您实际做过基准测试吗?我强烈建议您高估了调整大型
ArrayList
s的“性能影响”。(对于初学者来说,
add
是分期摊销的O(1),即使考虑到大小调整。)您的解决方案是拥有多个固定大小的数组并将它们连接到一个列表中,这看起来比纯ArrayList更好,但仍然无法保证连续分配,我创建了另一个固定数组以附加到以前的现有数组列表。有可能获得完全一致性吗?如果你想要完全连续性,你必须分配它。如果未分配内存,系统可以将其用于其他目的。如果您需要空间,那么您必须指出它,因此它将被保留。如果需要扩展并且无法准确预测大小,则需要使用列表(使用内存中的不同块)我刚刚检查了ArrayList的jdk内部实现,了解到internal它是用默认大小10初始化的,然后在需要扩展add()方法时执行相同的过程,创建新的数组+1大小->复制旧值等。因此,我认为它们位于连续的内存块内,但在重新调整大小时会影响性能。此算法在调整大小时不会影响性能,但在检索值时不会保证
O(1)
性能。您确定不保证O(1)吗?如果可能的话,我可以在提到文档的地方找到一些指针吗?我也在寻找类似于ex的东西。知道cur中最后一个元素的地址