我有一个应用程序,它形成所有可能的对,然后比较对,但是当我运行应用程序时,它给了我异常: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个数字,它形成了每一行的所有可能对。 有谁知道如何解决这个问题?感谢
答案 0 :(得分:1)
我的数学可能已关闭,但这可能就是为什么你的空间不足了。
每行40个数字,20000行= 800000个数字。
800000 C 2 = 319999600000数字组合。
4个字节int
和Pair<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.一对一,搜索文件得到行号包含两个数字对
抱歉,因为我的英语不好。