我有这段代码将StringBuilders的ArrayList转换为字符串的ArrayList:
代码:
public ArrayList<String> convGenSeqToString(ArrayList<StringBuilder> buff){
ArrayList<String> convBuf = new ArrayList<String>();
for (StringBuilder xVar: buff){
convBuf.add(xVar.toString());
}
return convBuf;
}
我的代码适用于15-20MB文本文件的文件。但是我有一个44MB的文本文件,每当我用该文本文件运行我的程序时,我总是会收到此错误。
错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2746)
at java.util.ArrayList.ensureCapacity(ArrayList.java:187)
at java.util.ArrayList.add(ArrayList.java:378)
at Recognition.convGenSeqToString(Recognition.java:157)
at Recognition.genSeq(Recognition.java:145)
at Recognition.Recognitions(Recognition.java:96)
at ChainDetection.main(Detection.java:25)
我已经使用-Xmx2048M增加了JVM运行配置中的内存,但仍然存在相同的错误。我将错误指向上面显示的代码并突出显示这一行:
convBuf.add(xVar.toString());
有没有其他方法可以在不使用.toString()
方法的情况下将StringBuilder转换为字符串?我在其他论坛中看到过,他们也为toString创建了自定义类,但我还不熟悉泛型和一些“@”关键字。任何人都有如何解决这个问题的建议或指导?
我根据vanza的建议编辑了我的代码 这是:
public ArrayList<String> convGenSeqToString(ArrayList<StringBuilder> buff){
ArrayList<String> convBuf = new ArrayList<String>(buff.size());
Iterator <StringBuilder> iterBuf = buff.iterator();
while (iterBuf.hasNext()){
StringBuilder x = iterBuf.next();
convBuf.add(x.toString());
iterBuf.remove();
}
return convBuf;
}
错误讯息:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.ArrayList.<init>(ArrayList.java:132)
at Recognition.convGenSeqToString(Recognition.java:154)
at Recognition.genSeq(Recognition.java:145)
at Recognition.Recognitions(Recognition.java:96)
at ChainDetection.main(ChainDetection.java:25)
我用buff.size()和没有buff.size()尝试了这个,我收到了同样的错误信息。但似乎我的错误消息现在减少到5。还有其他想法吗?提前谢谢!
答案 0 :(得分:5)
如果不了解您的计划,我将不会对您采取的方法发表任何评论,只会对您发布的代码发表评论。听起来很奇怪,44MB的文件正在填满2G堆。
您可以做的一件事是预先在目标数组中分配空间:
ArrayList<String> convBuf = new ArrayList<String>(buf.size());
这将避免ArrayList调整大小步骤,该步骤会创建现有列表的副本(并显示在堆栈跟踪中)。
您可以尝试的另一件事是在构建String数组时释放对原始StringBuilders的引用。使用Iterator(而不是“for each”循环),并在每次迭代时使用buff
从Iterator.remove()
数组中删除StringBuilder;这样你就可以释放一些内存,让垃圾收集器在你内存不足时回收。
但是,再次,你用这么小的文件耗尽内存听起来很奇怪。也许用jvisualvm查看你的堆可能会有所帮助。
答案 1 :(得分:1)
有两种方法可以从StringBuilder获取值
Reflection
并调用package protected
方法
getValue()这很难,我认为不是那么好。string
你将创建字符串的新实例,它将使用你的记忆。