制作一个非常大的Java数组

我试图找到Pólya猜想的一个反例,它将在9亿的某个地方。 我正在使用一种非常有效的算法,甚至不需要任何因式分解(类似于Eratosthenes的Sieve,但信息更多。因此,需要大量的整数。

该程序是高效和正确的,但需要一个arrays,直到想要检查的xi(它检查来自(2,x)的所有数字)。 所以,如果反例是9亿,我需要一个同样大的数组。 Java不会允许我超过2000万。 有什么我可以做的让一个大的数组?

您可能希望扩展JVM堆的最大大小。 您可以使用命令行选项执行此操作。

我相信它是-Xmx3600m(3600兆字节)

Java将允许多达20亿个数组条目。 这是你的机器(和有限的内存)无法处理如此大的数量。

Java数组由int索引,因此数组不能大于2 ^ 31(没有无符号整数)。 因此,数组的最大大小为2147483648,消耗(对于普通的int [])8589934592字节(= 8GB)。

因此,int-index通常不是限制,因为无论如何你都会耗尽内存。

在您的算法中,您应该使用List(或Map)作为您的数据结构,并选择可以超过2 ^ 31的List(或Map)实现。 这可能会变得棘手,因为“通常”实现ArrayList(和HashMap)在内部使用数组。 您必须实现自定义数据结构; 例如,通过使用2级数组(列表/数组)。 当你在它时,你也可以尝试更紧密地包装。

9亿32位整数没有进一步的开销 – 并且总会有更多的开销 – 需要略高于3.35 GiB。 获得大量内存的唯一方法是使用64位JVM(在具有至少8 GB RAM的计算机上)或使用一些磁盘备份缓存。

如果您不需要将所有内容一次性加载到内存中,则可以将其分段为文件并存储在磁盘上。

你是什​​么意思“不允许”。 您可能会收到OutOfMemoryError ,因此使用-Xmx命令行选项添加更多内存。

您可以定义自己的类,将数据存储在2d数组中,该数组将更接近sqrt(n)的sqrt(n)。 然后使用索引函数来确定数组的两个索引。 根据需要,这可以扩展到更多维度。

您将遇到的主要问题是RAM耗尽。 如果您达到此限制,则需要重新考虑算法或考虑外部存储(即文件或数据库)。

如果您的算法允许:

  • 在适合内存的切片中进行计算。

    您将不得不重做每个切片的计算,但它通常足够快。

  • 使用较小数字类型的数组,如byte。

对于有效存储的大型基元数组(boolean,byte,… double我建议我们的库JLargeArrays在GitHub上可用( https://github.com/IcmVis/JLar​​geArrays ) – 它存储任意大型数组,提供足够的内存,例如16 GB PC上的12G字节arrays,在Oracle和IBM JVM上进行了测试,具有良好的multithreading效率。

我为Project Euler编写了一个版本的Eratosthenes Sieve,它一次处理搜索空间的大块。 它处理前1M个整数(例如),但保留它在表中找到的每个素数。 在遍历到目前为止发现的所有素数之后,重新初始化数组,并且在找到下一个数组之前已经使用已发现的素数来标记数组。

该表将素数映射到数组起始处的“偏移量”,以进行下一次处理迭代。

这在概念(如果不是在实现中)类似于函数式编程语言执行列表的惰性评估的方式(尽管在更大的步骤中)。 不必预先分配所有内存,因为您只对通过测试的数组部分感兴趣。 保持非素数不变对你没用。

该方法还为以后的素数迭代提供了记忆。 它比扫描稀疏的筛子数据结构更快,每次都在寻找那些。

我第二个@sfossen的想法和@Aaron Digulla。 我会去磁盘访问。 如果您的算法可以接受List接口而不是普通数组,则可以将List中的适配器写入内存映射文件。

使用Tokyo Cabinet,Berkeley DB或任何其他基于磁盘的键值存储。 它们比任何传统数据库都快,但允许您使用磁盘而不是内存。

根据您访问arrays的方式,您可能会发现RandomAccessFile允许您使用大于内存的文件。 但是,您获得的性能非常依赖于您的访问行为。

你有可能获得9亿比特吗? (可能存储为字节数组)。

您可以尝试将其拆分为多个数组。

 for(int x = 0; x <= 1000000; x++){ myFirstList.add(x); } for(int x = 1000001; x <= 2000000; x++){ mySecondList.add(x); } 

然后迭代它们。

 for(int x: myFirstList){ for(int y: myFirstList){ //Remove multiples } } //repeat for second list 

请改用内存映射文件(Java 5 NIO软件包)。 或者将筛子移动到一个小的C库中并使用Java JNI 。