解析 CSV 时出现 OutOfMemoryError
OutOfMemoryError while parsing CSV
我有一个巨大的 csv 文件 (500MB) 和 400k 条记录
id, name, comment, text
1, Alex, Hello, I believe in you
栏目文字包含很多信息和句子。我想获取此列("Text"),将所有非字母符号替换为“”,并按倒序排列,从 "Text" 列中最常见的单词到最不常见的单词,限制为 1000。这是它看起来如何。我正在使用 CsvReader 库
CsvReader doc = new CsvReader("My CSV Name");
doc.readHeaders();
try {
List<String> listWords = new ArrayList<>();
while (doc.readRecord()) {
listWords.addAll(Arrays.asList(doc.get("Text"/*my column name*/).replaceAll("\P{Alpha}", " ").toLowerCase().trim().split("[ ]+")));
}
Map<String, Long> sortedText = listWords.stream()
.collect(groupingBy(chr -> chr, counting()))
.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Collections.reverseOrder()))
.limit(1000)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
sortedText.forEach((k, v) -> System.out.println("Word: " + k + " || " + "Count: " + v));
doc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
doc.close();
}
在 运行 之后,我的 GC 超出了内存不足错误。如何做到最好?我无法增加堆大小,我只需要使用默认设置
问题建议:不要在 listWords
中添加所有单词,而是尝试按处理的每个 CSV 行计算单词。
代码应该是这样的:
CsvReader doc = null;
try {
doc = new CsvReader(""My CSV Name");
doc.readHeaders();
Map<String, Long> mostFrequent = new HashMap<String, Long>();
while (doc.readRecord()) {
Arrays.asList(doc.get("text"/*my column name*/).replaceAll("\P{Alpha}", " ").toLowerCase().trim().split("[ ]+")).
stream().forEach(word -> {
if (mostFrequent.containsKey(word)) {
mostFrequent.put(word, mostFrequent.get(word) + 1);
}
else {
mostFrequent.put(word, 1l);
}
});
}
Map<String, Long> sortedText = mostFrequent.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(1000)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
sortedText.forEach((k, v) -> System.out.println("Word: " + k + " || " + "Count: " + v));
doc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
doc.close();
}
我有一个巨大的 csv 文件 (500MB) 和 400k 条记录
id, name, comment, text
1, Alex, Hello, I believe in you
栏目文字包含很多信息和句子。我想获取此列("Text"),将所有非字母符号替换为“”,并按倒序排列,从 "Text" 列中最常见的单词到最不常见的单词,限制为 1000。这是它看起来如何。我正在使用 CsvReader 库
CsvReader doc = new CsvReader("My CSV Name");
doc.readHeaders();
try {
List<String> listWords = new ArrayList<>();
while (doc.readRecord()) {
listWords.addAll(Arrays.asList(doc.get("Text"/*my column name*/).replaceAll("\P{Alpha}", " ").toLowerCase().trim().split("[ ]+")));
}
Map<String, Long> sortedText = listWords.stream()
.collect(groupingBy(chr -> chr, counting()))
.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Collections.reverseOrder()))
.limit(1000)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
sortedText.forEach((k, v) -> System.out.println("Word: " + k + " || " + "Count: " + v));
doc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
doc.close();
}
在 运行 之后,我的 GC 超出了内存不足错误。如何做到最好?我无法增加堆大小,我只需要使用默认设置
问题建议:不要在 listWords
中添加所有单词,而是尝试按处理的每个 CSV 行计算单词。
代码应该是这样的:
CsvReader doc = null;
try {
doc = new CsvReader(""My CSV Name");
doc.readHeaders();
Map<String, Long> mostFrequent = new HashMap<String, Long>();
while (doc.readRecord()) {
Arrays.asList(doc.get("text"/*my column name*/).replaceAll("\P{Alpha}", " ").toLowerCase().trim().split("[ ]+")).
stream().forEach(word -> {
if (mostFrequent.containsKey(word)) {
mostFrequent.put(word, mostFrequent.get(word) + 1);
}
else {
mostFrequent.put(word, 1l);
}
});
}
Map<String, Long> sortedText = mostFrequent.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(1000)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
sortedText.forEach((k, v) -> System.out.println("Word: " + k + " || " + "Count: " + v));
doc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
doc.close();
}