Java 循环通过中等大小数据集时Kotlin内存不足错误
我正在Kotlin中运行下面的循环,并抛出内存不足错误。我运行此命令是为了读取csv文件中的行。“记录”的大小为6422 我有同样的逻辑在Java中执行,但它工作得很好。下面是我在Java中的内容Java 循环通过中等大小数据集时Kotlin内存不足错误,java,memory,kotlin,jvm,out-of-memory,Java,Memory,Kotlin,Jvm,Out Of Memory,我正在Kotlin中运行下面的循环,并抛出内存不足错误。我运行此命令是为了读取csv文件中的行。“记录”的大小为6422 我有同样的逻辑在Java中执行,但它工作得很好。下面是我在Java中的内容 private static List<String> readCSVFile(String filePath) throws IOException { Reader in = new FileReader(filePath); Iterable<CSVRecord
private static List<String> readCSVFile(String filePath) throws IOException {
Reader in = new FileReader(filePath);
Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(in);
List<String> rows = new ArrayList<>();
for (CSVRecord record : records) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < record.size(); i++)
builder.append(record.get(i) + ",");
builder.deleteCharAt(builder.length() - 1);
rows.add(builder.toString());
}
return rows;
}
private static List readCSVFile(字符串文件路径)引发IOException{
Reader in=新文件读取器(文件路径);
Iterable records=CSVFormat.DEFAULT.parse(in);
列表行=新建ArrayList();
用于(CSVRecord记录:记录){
StringBuilder=新的StringBuilder();
对于(int i=0;i
为什么Kotlin对此有问题?我是不是在循环方面出了问题?任何帮助都将不胜感激,因为我是Kotlin的新手。我认为您的代码中有一个bug
records.forEach() {
output = "" // clear output ;)
...
}
将其与java代码进行比较
for (CSVRecord record : records) {
StringBuilder builder = new StringBuilder(); // clear builder
...
}
在kotlin代码中也使用
StringBuilder
。您正在创建堆中String
对象的日志。字符串是不可变的,此代码:
var output = ""
output = output + ","
正在堆中创建两个对象,尽管您只能引用其中一个对象。因此,另一个符合GC删除它的条件。在您的情况下,GC“工作”太辛苦了,这就是为什么您会得到java.lang.OutOfMemoryError:超出了GC开销限制
fun readCSVFile(filePath: String): List<String> {
val reader = FileReader(filePath)
val records = CSVFormat.DEFAULT.parse(reader)
val rows = mutableListOf<String>()
var output = StringBuilder("")
records.forEach() {
output = StringBuilder("")
val size = it.size()
for (i in 0 until it.size()-1) {
output = output.append(it.get(i) + ",")
}
output.deleteCharAt(output.length - 1)
rows.add(output.toString())
}
return rows
}
fun readCSVFile(文件路径:字符串):列表{
val reader=FileReader(filePath)
val records=CSVFormat.DEFAULT.parse(读取器)
val rows=mutableListOf()
变量输出=StringBuilder(“”)
forEach()记录{
输出=StringBuilder(“”)
val size=it.size()
for(在0中输入i,直到它.size()-1){
output=output.append(it.get(i)+“,”)
}
output.deleteCharAt(output.length-1)
rows.add(output.toString())
}
返回行
}
您的代码运行速度也会快得多,因为创建新对象的成本相当高。您的Kotlin代码中有两个问题:
output=“
”——对于每个迭代,您的输出中都有以前的所有行您正在阅读的CSV大小是多少?你的JVM的-Xmx值是多少(如果你自己定义的话)?对不起,我编辑了这个问题。是6422字节吗?另外,您是否在任何地方定义了-Xmx或它是默认值?我想答案已经解决了问题,所以这是为了解决另一个问题:将0中的
I替换为it.size()-1
,将0中的I替换为it.size()
或I in 0..it.size()-1
,因为它丢失了最后一行。您尝试过吗?我不认为这会有帮助,因为OP的GC开销限制超过了,这意味着heapI中有很多对象同意StringBuilder会有帮助,但这也会有帮助,因为这是GC必须运行那么多次的原因。rows.add(输出)->rows.add(“row1”);rows.add(输出)->rows.add(“row1row2”);rows.add(输出)->rows.add(“row1row2row3”);rows.add(输出)->rows.add(“row1row2row3…row6422”);这不会以任何方式影响GC运行行的时间。添加(输出)
,字符串只是不断变大,OP的错误字符串不断变大,堆内存不足,将导致GC运行。GC一直试图释放内存,但几乎无法完成任何工作,因为行内容不能被垃圾收集。
var output = ""
output = output + ","
fun readCSVFile(filePath: String): List<String> {
val reader = FileReader(filePath)
val records = CSVFormat.DEFAULT.parse(reader)
val rows = mutableListOf<String>()
var output = StringBuilder("")
records.forEach() {
output = StringBuilder("")
val size = it.size()
for (i in 0 until it.size()-1) {
output = output.append(it.get(i) + ",")
}
output.deleteCharAt(output.length - 1)
rows.add(output.toString())
}
return rows
}