如何将数组大小扩展到java中的long范围以及如果不能可能其他什么数据结构可以用于相同用途
Java 数组是内置结构。您无法以任何方式影响他们的索引方案,因此您必须使用
int
索引。
类似地,所有 Java 集合都限制为 231 条目,因为它们的
size()
方法返回 int
,并且直接访问方法(如果可用)也采用 int
。
如果您需要一个存储超过 231 项的数据结构,请创建一个“块”的二维数组,每个块代表“大”数组的一部分。本质上,您将构建自己的类,将
long
寻址转换为一对 int
以模拟线性索引空间。
Java 数组的大小是固定的。当您创建一个新数组并为其分配大小时,它不能扩展或缩小,但只要数组的类型相同,就可以轻松更改数组的内容。 java中的数组必须在数组内包含相同的数据类型。
例如:
int[] a = new int[5];
正在创建一个可以存储整数的大小的新数组。 如果您想要一支可以增加规模的军队,我建议使用称为动态数组的数据类型。在java中,动态数组称为ArrayList。数组列表是动态的,因此在创建 ArrayList 时无需设置大小,但必须定义数组列表的类型 例如:
Arraylist<Integer> a = new ArrayList<Integer>();
java 数组限制为 231 少一些元素,具体取决于特定的 VM 实现。
解决此问题的一种方法是使用数组的数组,单个数组的最大长度为 231 - 8 个元素,因此确保我们不会超过 VM 限制
long wishedArraySize = 3_000_000_000L;
long maxVMArraySize = 2_147_483_639; // Integer.MAX_VALUE - 8
byte[][] myHugeArray = new byte[(int)((wishedArraySize - 1L) / maxVMArraySize + 1L)][];
for (int i = 0; i < myHugeArray.length; ++i) {
myHugeArray[i] = new byte[(int)(i < myHugeArray.length - 1 ? maxVMArraySize : (wishedArraySize - i * maxVMArraySize))];
}
long index = 2_345_678_901L; // random number > 2 Gig
System.out.println(myHugeArray[(int)(index / maxVMArraySize)][(int)(index % maxVMArraySize)]);
如果我们坚持使用 2 的幂的倍数数组大小,我们可以优化并避免这些除法和模运算。2 的最大幂是 1 Gig 元素
long wishedArraySize = 3_000_000_000L;
long maxPowerOf2ArraySize = 1L << 30; // 1 Gig == 1_073_741_824 == 2^30
byte[][] myHugeArray = new byte[(int)(((wishedArraySize - 1L) >> 30) + 1L)][];
for (int i = 0; i < myHugeArray.length; ++i) {
myHugeArray[i] = new byte[(int)(i < myHugeArray.length - 1 ? maxPowerOf2ArraySize : (wishedArraySize - i * maxPowerOf2ArraySize))];
}
long lowerThan1GigMask = 0x0_3f_ff_ff_ffL; // == 1_073_741_823 == 2^30 - 1
long index = 2_345_678_901L; // random number > 2 Gig
System.out.println(myHugeArray[(int)(index >> 30)][(int)(index & lowerThan1GigMask)]);
我们可以将它们很好地放在一个类中,但主要区别在于访问数组,从
myLimitedArray[index]
到 myHugeArray[(int)(index >> 30)][(int)(index & lowerThan1GigMask)]