【问题标题】:How to store 100 million integers in a Java array?如何在 Java 数组中存储 1 亿个整数?
【发布时间】:2013-02-02 21:00:19
【问题描述】:

我正在做一个小任务,我需要在一个数组中存储大约 10 亿个整数。但是,我遇到了堆空间问题。你能帮我解决这个问题吗?

机器详情:Core 2 Duo 处理器,4 GB RAM。我什至尝试过 -Xmx 3072m 。有什么解决方法吗? 同样的事情在 C++ 中也有效,所以肯定有办法在内存中存储这么多数字。

下面是我得到的代码和异常:

public class test {
    private static int C[] = new int[10000*10000];

    public static void main(String[] args) {
        System.out.println(java.lang.Runtime.getRuntime().maxMemory()); 

    }

}

例外: 线程“主”java.lang.OutOfMemoryError 中的异常:Java 堆空间 在测试中。(test.java:3)

【问题讨论】:

  • 我们需要更多信息来回答这个问题...这些整数是随机的吗?他们的范围是多少?他们的顺序重要吗?可以重复吗?
  • 你知道java -mx对吗?
  • @MiserableVariable:要存储 10 亿个 ints,您需要大约 4GB 的堆空间。这并不总是可用的......
  • 可能重复的问题:stackoverflow.com/questions/650274/…
  • 这里几乎所有的回复都倾向于一种更有效地存储数据的方法,这是因为很有可能您尝试完成的工作无需将所有 10 亿个数字同时存储在内存中。如果您分享有关数据访问模式的详细信息,您可能会得到更有意义的回复。

标签: java arrays memory integer


【解决方案1】:

使用关联数组。键是整数,值是计数(整数被添加到列表中的次数)。

如果分布相对随机,这应该可以为您节省一些可观的空间,如果不是,则更是如此。

【讨论】:

  • 好主意。真的,这个大小的数组中应该有很多重复的值。
  • @Dave:一个哈希表,至少在 Java 库中实现是最糟糕的方法之一。空间效率。只有当您只有几个具有高出现频率的整数时,您的方法才有意义......
  • @Dave:这就是重点:大多数关联数组的每个条目都有很大的开销。除非重复很多整数,否则原始 int[] 可能仍然更好......
  • @thkala:只有在空间不足时才会更好:)
【解决方案2】:

如果您需要存储 10 亿个完全随机的整数,那么恐怕您确实需要相应的空间,即大约 4GB 的内存用于 32 位 int 数字。您可以尝试增加 JVM 堆空间,但您需要有一个 64 位操作系统和至少一样多的物理内存——而且您只能做到这一点。

另一方面,如果您可以利用应用程序中的特定约束,您可能能够更有效地存储这些数字。

例如如果您只需要知道一个特定的 int 是否包含在一个集合中,您可以使用一个位集合 - 即 int 范围内的每个值的一个位。这大约是 40 亿位,即 512 MB - 一个更合理的空间需求。例如,少数BitSet 对象可以覆盖整个 32 位整数范围,而无需编写任何位处理代码...

【讨论】:

  • RAM 不是我们唯一的内存。还有交换。
  • @AudriusMeškauskas:是的,但据我所知,JVM 绝对会拒绝分配比物理 RAM 更多的堆...
  • 我不相信。你在哪里看到过这个文件? RAM 和交换类型之间的差异对于程序应该是透明的。但可能会很慢。
  • @AudriusMeškauskas:抱歉,现代 JVM 似乎确实是这种情况。我的 JVM 会很高兴地以 -Xmx80g 开头,这实际上比我系统上的 RAM+swap 还要多……
  • 当然,取决于对所有ints 所做的事情,使用交换空间可能比手动计算要好一点:-)
【解决方案3】:

可能使用内存映射文件会有帮助吗?它们不是从堆中分配的。 这是一篇如何创建矩阵的文章。数组应该更简单。

Using a memory mapped file for a huge matrix - Peter Lawrey

【讨论】:

    【解决方案4】:

    您可以在 32 位系统上增加到 4GB。 如果您使用的是 64 位系统,则可以更高。

    输入 cmd 这个

    java -Xmx4g programname
    

    【讨论】:

    • 32位进程的地址空间只有2GB(3GB启用大地址感知)
    【解决方案5】:

    由于阵列这么大可能无法放入您的 RAM,因此您需要配置足够的 HDD 交换空间。在这些时候,4 - 16 Gb 的交换看起来并不现实。

    Java 只允许使用int 作为数组的索引,而不是long。因此,最大可能的数组可以有 2147483648 个值,足够了。

    使用-Xmx 提高默认情况下可能不足的内存上限。 3072m 是不够的,因为 10 亿个整数需要大约 4 Gb。由于操作系统等也需要空间,因此具有 4 Gb RAM 的机器无法在内存中保存所有 4 Gb 数据结构。

    JRE 或操作系统也可能拒绝一次性授予这么大的一块内存,需要分配一些较小的块(可能是数组或数组)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 2011-11-02
      • 2011-09-03
      • 1970-01-01
      • 2012-10-02
      • 2017-11-10
      相关资源
      最近更新 更多