如何在Java中创建一个大数组

7

我想创建一个布尔数组,其大小由用户输入。例如-用户可能会输入一个很大的数字,如1000000000000;那么我就必须创建一个大小为1000000000000的布尔数组。我面临的问题是,我无法将输入存储为int,因为它无法容纳如此庞大的数字-因此我无法创建数组。双精度是一个选择。我可以将输入数字存储为double,但我不知道如何创建与双精度数字相同大小的数组。这就是想法-

Scanner scanner = new Scanner(System.in);
int target = scanner.nextInt();
boolean [] array_a=new boolean [(target)];

如果目标超过int范围,这种方法将不起作用。需要帮助。

更新:谢谢大家。因此,您只能创建大小为int最大范围的数组(即2147483648),对于内存方面我之前没有考虑到。我会采取不同的方法。


你可以使用内存映射文件来提供每个布尔值所需的一位存储,需要128GB的磁盘空间。显然,你希望拥有同样数量的内存,但即使没有这么多内存也可以工作(但速度会降低)。 - Peter Lawrey
5个回答

11

在Java中,你不能创建大小大于最大正整数int的数组,因为数组索引是int。(同样适用于各种List实现。你也许可以创建更多条目的数组(例如,LinkedList),但是像getsize这样的操作开始变得不太正常,你只能通过一个iterator来获取较晚的条目(假设事情没有完全破碎),这需要很长时间。)

似乎你真的不可能需要创建一个具有超过2,147,483,647个元素的boolean数组,但如果你确实需要,你将不得不创建多个数组,并通过对索引进行取模来选择正确的数组(索引需要是long)。 (或者使用某些非JDK库,如果存在的话。)那将需要大约4G的RAM。可行,但很有可能完全采用不同的方法会更好。

但是1,000,000,000,000个元素?那将需要大约1-2 TB的RAM。正如NPE所说,如果你不在超级计算机上运行,你将不会有那么多的RAM。


1
实际上,你可以创建一个比那个更大的 LinkedList。但是你不会想在它上面使用 get(int) :-) - Stephen C
1
@StephenC:你有试过这样做吗?我强烈怀疑它会崩溃。无论如何,内存使用量都会很大(所有这些双链接指针)。 - T.J. Crowder
2
我没有尝试过。但是size()方法的List javadoc专门允许列表的大小大于MAX_INT。 - Stephen C
@StephenC:哦,原来是这样。 - T.J. Crowder
谢谢 :) 我明白了。采用了不同的方法。 - Tahniat Ashraf

8
你的问题不在于此。你最大的问题是没有足够的内存来分配一个有1,000,000,000,000个元素的数据结构(即使你克服了int索引的限制)。你需要重新考虑算法。

2
即使您拥有一个具有如此多可寻址内存的系统,Java数组也仅限于(2 ^ 31-1)个元素。这个限制甚至更为基本。 - Stephen C
@StephenC:这就是为什么我说“数据结构”而不是“数组”。一个人可以很容易地创建一个数组的数组或类似的东西,但那只会推迟不可避免的结果。 - NPE
1
2,147,483,647 个字大小的条目只需要约4G的内存。许多系统都有这个容量。虽然我不否认你的主要观点。 :-) - T.J. Crowder
@T.J.Crowder:这个数字从哪里来的?OP在谈论一万亿个元素。 - NPE
实际上,你说的是“数组”。 - Stephen C
@NPE:抱歉,你说得很对。那个数字是Integer.MAX_VALUE。我当时只关注了超过这个值的数组,忽略了示例数字。但是,你完全正确地使用了OP的示例值。 - T.J. Crowder

1
如何使用HashMap并使用长键和布尔值。
有几个优点:
1.您可以在long范围内使用索引
2.您不必担心使用的项目索引的最大大小。 只要是long就可以工作
3.您不会提前为整个集合分配内存。 相反,您只会使用所需的内存。

1
你可以创建一个抽象层,例如数组的数组(你甚至可以修改这个)。
Object [][] 可以是布尔值或其他类型。
class LargeArray {

    private final long size;
    private final int sizeI;
    private final int sizeJ;
    private final Object [][] objects;


    public LargeArray() {
        sizeI = 3;//Any reasonable value;
        sizeJ = Integer.MAX_VALUE;
        objects = new Object [sizeI][sizeJ];
        size = sizeI * sizeJ;
    }

    public long size() {
        return size;
    }

    public Object get(long index) {
         int i = index / sizeJ;
         int j = index % sizeJ;
         return objects[i][j];
    }

    public void set(long index, Object object) {
         int i = index / sizeJ;
         int j = index % sizeJ;
         objects[i][j] = object;
    }
}

您还可以更改第一维,比如说3。在这种情况下,对象[3][Integer.MAX_VALUE],您可以创建(2^31 -1)*3 = 2,147,483,647 * 3 = 6442450941个元素,您将需要(2^31 - 1)*3 * 4 =~ 23 GB的RAM,这实际上是可能的!!! :)


0
首先:你需要一个很好的理由来分配这么多内存。正如其他人所说,你可能需要重新考虑方法。
一些建议:要么将分配的数量限制为某个最大值,要么将其存储在文件中并寻找数据,或者按需分配(惰性分配)。如果数据是稀疏的(实际布尔值很少,但索引非常广泛),那么使用映射会更好。如果主要是零,请考虑仅存储1个 :)
第二:如果你打包位,理论上可以分配8倍于最大数组大小的布尔值。参见此讨论以获得灵感:在Java中实现C风格的位域

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接