exception:OutOfMemoryError:运行代码时的Java堆空间

时间:2010-10-13 04:47:00

标签: java out-of-memory

我有一个应用程序,它形成所有可能的对,然后比较对,但是当我运行应用程序时,它给了我异常:OutOfMemoryError:运行代码时的Java堆空间。我试过-Xmx1500m,但例外情况不断发生。 生成对的代码如下

File file = ...;

final Map<Pair, Collection<Integer>> lineNumbersByPair = new HashMap<Pair, Collection<Integer>>();

/*
 * Step 1: Read in the lines, one by one.
 */
Reader reader = new FileReader(file);
try {
    BufferedReader bufferedReader = new BufferedReader(reader);
    try {
        String line;

        int lineNumber = 0;
        while ((line = bufferedReader.readLine()) != null) {
            lineNumber++;

            String[] tokens = line.split("\\s+");
            int[] values = new int[tokens.length];

            for (int i = 0; i < tokens.length; i++) {
                values[i] = Integer.parseInt(tokens[i]);
            }

            for (int i = 0; i < values.length; i++) {
                for (int j = i + 1; j < values.length; j++) {
                    Pair pair = new Pair(values[i], values[j]);

                    Collection<Integer> lineNumbers;
                    if (lineNumbersByPair.containsKey(pair)) {
                        lineNumbers = lineNumbersByPair.get(pair);
                    } else {
                        lineNumbers = new HashSet<Integer>();
                        lineNumbersByPair.put(pair, lineNumbers);
                    }
                    lineNumbers.add(lineNumber);
                }
            }
        }
    } finally {
        bufferedReader.close();
    }
} finally {
    reader.close();
}

/*
 * Step 2: Identify the unique pairs. Sort them according to how many lines they appear on (most number of lines to least number of lines).
 */
List<Pair> pairs = new ArrayList<Pair>(lineNumbersByPair.keySet());
Collections.sort(
        pairs,
        new Comparator<Pair>() {
            @Override
            public int compare(Pair pair1, Pair pair2) {
                Integer count1 = lineNumbersByPair.get(pair1).size();
                Integer count2 = lineNumbersByPair.get(pair2).size();
                return count1.compareTo(count2);
            }
        }
    );
Collections.reverse(pairs);

/*
 * Step 3: Print the pairs and their line numbers.
 */
for (Pair pair : pairs) {
    Collection<Integer> lineNumbers = lineNumbersByPair.get(pair);
    if (lineNumbers.size() > 1) {
        System.out.println(pair + " appears on the following lines: " + lineNumbers);
    }
}

我正在读取一个大约15mb的文件,它包含20000行的单个数字,每行大约有40个数字,它形成了每一行的所有可能对。 有谁知道如何解决这个问题?感谢

2 个答案:

答案 0 :(得分:1)

我的数学可能已关闭,但这可能就是为什么你的空间不足了。

每行40个数字,20000行= 800000个数字。

800000 C 2 = 319999600000数字组合。

4个字节intPair<int, int>,每个对至少为8个字节,然后将其添加到数据结构中。

8字节* 319999600000 = 2+太字节。

重新阅读问题后,每一行都与下一行分开。

每行40个数字=&gt; 40 C 2 =每行780个组合* 20000行= 15600000个可能的唯一对*每对8个字节=在最坏的情况下仅为int的119 MB。再加上引用占用的内存,因为Java不允许集合中的基本类型。

但在再看一下你的节目后,我有一些建议:

为什么要将Pair映射到Set<Integer>

如果您只对每个Pair的出现次数感兴趣,则无需跟踪对出现的行号 - 您只想存储它出现的次数

因此,在这种情况下,您希望将Pair映射到Integer。这可以减少您需要的内存量。

您是否关心订购该对?

您的for循环似乎表明您不关心排序,即该对(30,45)与该对(45,30)相同。如果是这样,您应该根据对中的相对排序创建Pair。也许首先根据最小值创建Pair,这样每次遇到两个整数m和n时,总是会创建Pair(m, n)对。另请参阅有关hashCode()equals()的下一部分。

您是否实施了Pair的{​​{1}}和int hashCode()方法?

这可能是实际工作程序与破坏程序之间的差异。

在您的情况下,您希望boolean equals(Object)个对象测试逻辑相等,因为它是一个自定义类,因此您必须覆盖并实现自己的Pair方法。您还需要覆盖equals(Object),因为在覆盖hashCode()时必须始终这样做。

这在优秀的有效Java中有详细说明,以下是讨论此内容的章节示例:http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

答案 1 :(得分:0)

当数据太大而无法容纳内存时,唯一的方法是使用扩展内存(HDD)。 在这里,您可以在磁盘上进行分区和存储,将每个小部分加载到内存中并进行搜索。

或者你应该使用一个使用更少内存和更多处理器的algobrithm。
1.搜索文件,搜索所有数字,并创建一个相对的二维矩阵或类似下面的内容。

  1 2 3 4 ...
1 0 1 0 0
2 0 1 0 0
3 0 0 0 0
...


2.你可以对这个矩阵进行排序。
3.一对一,搜索文件得到行号包含两个数字对 抱歉,因为我的英语不好。