从StringBuilder转换为toString的Java替代方案

dim*_*mas 1 java memory string stringbuilder

我有这段代码将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;
    }
Run Code Online (Sandbox Code Playgroud)

我的代码适用于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)
Run Code Online (Sandbox Code Playgroud)

我已经使用-Xmx2048M增加了JVM运行配置中的内存,但仍然存在相同的错误.我将错误指向上面显示的代码并突出显示以下行:

convBuf.add(xVar.toString());
Run Code Online (Sandbox Code Playgroud)

有没有其他方法可以将StringBuilder转换为字符串而不使用该.toString()方法?我在其他论坛中看到过,他们也为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;
    }
Run Code Online (Sandbox Code Playgroud)

错误信息:

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)
Run Code Online (Sandbox Code Playgroud)

我尝试使用buff.size()和没有buff.size(),我得到了相同的错误消息.但似乎我的错误消息现在减少到5.还有其他想法吗?提前致谢!

van*_*nza 5

如果不了解您的计划,我将不会对您采取的方法发表任何评论,只会对您发布的代码发表评论.听起来很奇怪,一个44MB的文件填满了2G堆.

您可以做的一件事是预先在目标数组中分配空间:

ArrayList<String> convBuf = new ArrayList<String>(buf.size());
Run Code Online (Sandbox Code Playgroud)

这将避免ArrayList调整大小步骤,该步骤创建现有列表的副本(并显示在堆栈跟踪中).

您可以尝试的另一件事是在构建String数组时释放对原始StringBuilders的引用.使用Iterator(而不是"for each"循环),并在每次迭代时buff使用数组中的StringBuilder Iterator.remove(); 这样你就可以释放一些内存,让垃圾收集器在内存不足的情况下回收.

但同样,使用如此小的文件耗尽内存听起来很奇怪.也许用jvisualvm查看你的堆可以解决一些问题.