1

StringBuildersのArrayListをStringsの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());

メソッドを使用せずに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;
    }

エラーメッセージ:

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に減ったようです。これについて他に何か考えはありますか?前もって感謝します!

4

2 に答える 2

5

あなたのプログラムについてもっと知ることなく、私はあなたが取ったアプローチについてコメントすることを控え、あなたが投稿したコードについてのみコメントします。しかし、44MBのファイルが2Gのヒープを埋めているのは奇妙に聞こえます。

実行できることの1つは、ターゲット配列にスペースを事前に割り当てることです。

ArrayList<String> convBuf = new ArrayList<String>(buf.size());

これにより、既存のリストのコピーを作成する(そしてスタックトレースに表示される)ArrayListのサイズ変更手順が回避されます。

試すことができるもう1つのことは、String配列の構築中に、元のStringBuildersへの参照を解放することです。(「foreach」ループの代わりに)イテレータを使用し、各反復でbuffを使用して配列からStringBuilderを削除します。Iterator.remove()そうすれば、メモリが不足している場合にガベージコレクタが再利用できるようにメモリを解放できます。

しかし、繰り返しになりますが、このような小さなファイルでメモリが不足しているのは奇妙に聞こえます。たぶん、jvisualvmでヒープを見ると、いくらかの光を当てることができます。

于 2012-07-08T19:26:42.407 に答える
1

StringBuilderから値を取得する方法は2つあります

  1. 最初に使用してメソッドgetValue()Reflectionを呼び出すのpackage protectedは難しいので、それほど良いとは思いません。
  2. 2番目の呼び出しメソッドgetChars

ところで、charの配列があり、使用stringするために文字列の新しいインスタンスを作成し、メモリを使用します。

于 2012-07-08T19:32:59.407 に答える