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

异常:OutOfMemoryError:运行代码时的Java堆空间,java,out-of-memory,Java,Out Of Memory,我有一个应用程序,它形成所有可能的对,然后比较这些对,但是当我运行应用程序时,它给了我一个异常:OutOfMemoryError:Java堆空间。我尝试了-Xmx1500m,但异常情况不断出现。 生成对的代码如下所示 File file = ...; final Map<Pair, Collection<Integer>> lineNumbersByPair = new HashMap<Pair, Collection<Integer>>();

我有一个应用程序,它形成所有可能的对,然后比较这些对,但是当我运行应用程序时,它给了我一个异常: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);
    }
}
文件=。。。;
最终映射lineNumbersByPair=newhashmap();
/*
*第一步:逐行阅读。
*/
Reader Reader=新文件读取器(文件);
试一试{
BufferedReader BufferedReader=新的BufferedReader(读卡器);
试一试{
弦线;
int lineNumber=0;
而((line=bufferedReader.readLine())!=null){
lineNumber++;
字符串[]标记=line.split(\\s+);
int[]值=新的int[tokens.length];
for(int i=0;i1){
System.out.println(pair+”出现在以下行:“+行号”;
}
}
我正在读一个15mb左右的文件,它包含20000行单数字,每行大约有40个数字,它形成了每行所有可能的对。
有人知道如何解决这个问题吗?谢谢

我的数学可能不好,但这可能就是你仍然没有空间的原因

所以每行40个数字,20000行=800000个数字

800000 C 2=31999600000个数字组合

一个
int
有4个字节,对于
Pair
,每对至少有8个字节,然后将其添加到数据结构中

8字节*319999600000=2+TB

重读你的问题后,每一行与下一行是分开的

每行40个数字=>40C2=780个组合每行*20000行=1560000个可能的唯一对*8字节每对=119MB在最坏的情况下纯粹用于
int
。再加上引用占用的内存,因为Java不允许在集合中使用基元类型

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

为什么要将
映射到

如果您只对每个
对的出现次数感兴趣,则不需要跟踪这些对出现的行号-您只需要存储它出现的次数

因此,在本例中,您希望将
映射到
整数
。这样可以减少所需的内存量

您关心这双鞋的订购吗?

您的
for
循环似乎表明您不关心订购,即配对(30,45)与配对(45,30)相同。如果是这样,您应该根据对中的相对顺序创建
对。可能首先基于最小值创建一个
,以便每次遇到两个整数m和n时,总是将该对创建为
对(m,n)
。另请参见下一节关于
hashCode()
equals()

您是否实现了
Pair
int hashCode()
布尔等于(对象)
方法?

这可能是实际工作程序和中断程序之间的差异

在您的例子中,您希望
Pair
对象测试逻辑相等性,因为它是一个自定义类,所以您必须重写并实现自己的
equals(Object)
方法。您还需要重写
hashCode()
,因为重写
equals()
时必须始终这样做


这在优秀有效的Java中有详细介绍,下面是一个讨论这一点的章节示例:

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

或者你应该使用一种使用更少内存和更多处理器的算法。
1.搜索文件,搜索所有num,并创建一个相对的二维矩阵或类似的东西

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

2.您可以在此矩阵上排序。
3.一对一对地搜索文件,以获得包含两个数字的行num。

很抱歉,我的英语不好。

对于较小的文件,您是否获得了正确的结果?到目前为止有成功的输出吗?是的,它在较小的文件上运行良好,并且输出都是goodstarcaller,正如J-16 SDiZ评论的和我发布的一样-这个问题就如同它一样