我正在尝试在java中实现面向列的数据存储引擎。我想知道是否有任何其他方法可以为动态增长的数组实现连续的内存分配。
HashMaps在扩展/调整大小时无法分配连续的内存块。
即使通过创建更大尺寸的新固定数组并将旧固定数组中的值复制到此新数组看起来是实现连续性的唯一选项,但与ex相比,这是非常慢的。假设您已经在当前大小为100万的列(固定数组)中有100万条记录,并且您需要在1000001位置插入新值,那么jvm必须创建大小为1000001的新数组并将所有值复制到新的更大的数组(只是为了插入一个值)并保持连续性。
如上所述,ArrayList的内部工作方式与内部相同(分配新数组+复制旧值等)。因此,作为具有额外的线程安全同步开销的向量。
因此,通过在初始化期间创建一个巨大的固定阵列来分配大型连续内存的另一种方法会导致许多未使用的内存,并且不是一个可行的解决方案。
如果有更好的选择,请提供帮助。对于前者类似的东西(如果有可能在Java中实现)知道当前固定数组中最后一个元素的地址,并以某种方式检查下一个连续可用的块是否可用?如果是这样,那么使用它来存储新值以及更新数组索引以容纳这个新的更改以维持O(1)时间读取访问?
谢谢。
答案 0 :(得分:0)
有很多黑客攻击,但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)
)
答案 1 :(得分:0)
如果您是“手动”尝试这样做,一种常见的技术是每次需要增加时将数组的大小加倍。因此,在您的示例中,您可以将阵列大小调整为200万;这很贵,但这意味着您不需要再长时间调整大小。
这为您提供了分摊常量时间的数组插入,尽管偶尔可能需要进行昂贵的操作(例如复制100万行),因此您可能不得不修改此想法以满足您的特定需求。有关动态数组实现的更多讨论,请参阅http://en.wikipedia.org/wiki/Dynamic_array。