1

約 50,000 行でサイズが 1.1MiB の csv ファイルを読み込んでいます (さらに大きくなる可能性があります)。

Code1 では String を使用して csv を処理し、Code2 では StringBuilder を使用します (コードを実行するスレッドは 1 つだけなので、同時実行性の問題はありません)。

StringBuilder を使用すると、通常の String クラスを使用する場合よりもコードが読みにくくなります。

Code2 の StringBuilder を使用して、ヒープ スペースとメモリを少し節約するために時期尚早に最適化していませんか?

コード1

            fr = new FileReader(file);
            BufferedReader reader = new BufferedReader(fr);

            String line = reader.readLine();
                while ( line != null )
                {
                    int separator = line.indexOf(',');
                    String symbol = line.substring(0, seperator);
                    int begin = separator;
                    separator = line.indexOf(',', begin+1);
                    String price = line.substring(begin+1, seperator);

                    // Publish this update
                    publisher.publishQuote(symbol, price);

                    // Read the next line of fake update data
                    line = reader.readLine();
                 }

コード 2

                    fr = new FileReader(file);
                    StringBuilder stringBuilder = new StringBuilder(reader.readLine());

                while( stringBuilder.toString() != null ) {
                    int separator = stringBuilder.toString().indexOf(',');
                    String symbol = stringBuilder.toString().substring(0, separator);
                    int begin = separator;
                    separator = stringBuilder.toString().indexOf(',', begin+1);
                    String price = stringBuilder.toString().substring(begin+1, separator);
                    publisher.publishQuote(symbol, price);

                    stringBuilder.replace(0, stringBuilder.length(), reader.readLine());
                }

編集

toString() 呼び出しを削除したため、生成される文字列オブジェクトが少なくなります。

コード3

while( stringBuilder.length() > 0 ) {
                    int separator = stringBuilder.indexOf(",");
                    String symbol = stringBuilder.substring(0, separator);
                    int begin = separator;
                    separator = stringBuilder.indexOf(",", begin+1);
                    String price = stringBuilder.substring(begin+1, separator);
                    publisher.publishQuote(symbol, price);
                    Thread.sleep(10);
                    stringBuilder.replace(0, stringBuilder.length(), reader.readLine());
                }

また、元のコードはhttp://www.devx.com/Java/Article/35246/0/page/1からダウンロードします

4

5 に答える 5

3

最適化されたコードはアプリのパフォーマンスを向上させますか? - 私の質問

2 番目のコード サンプルでは、​​メモリも計算時間も節約されません。の目的を誤解しているかもしれませんがStringBuilder、これは実際には文字列を作成するためのものであり、文字列を読み取るためのものではありません。

ループまたは 2 番目のコード サンプル内では、すべての行に expression が含まれておりstringBuilder.toString()、基本的にバッファリングされた文字列をStringオブジェクトに何度も変換しています。実際の文字列操作は、これらのオブジェクトに対して行われます。最初のコード サンプルは読みやすいだけでなく、確実に 2 つのコード サンプルと同等のパフォーマンスを発揮します。

StringBuilder で物事を時期尚早に最適化していますか? - あなたの質問

アプリケーションのプロファイリングを行い、これらの行が実行速度を大幅に低下させるという結論に達しない限り、そうです。何かが遅くなることが本当に確実でない限り (たとえば、計算が非常に複雑であると認識している場合)、コードの可読性を損なう最適化を行う前に、何らかのプロファイリングを行いたいと思うことは間違いありません。

このコードに対してどのような最適化を行うことができますか? - 私の質問

Scannerアプリケーションのプロファイリングを行い、これが最適化の適切な場所であると判断した場合は、クラスが提供する機能を調べることを検討する必要があります。実際、これにより、パフォーマンスが向上し (これが真かどうかはプロファイリングでわかります)、より単純なコードが得られる可能性があります。

于 2010-04-07T14:53:55.667 に答える
2

Code2 の StringBuilder を使用して、ヒープ スペースとメモリを少し節約するために時期尚早に最適化していませんか?

おそらく:はい. ただし、これを確認する唯一の方法は、コードをプロファイリングすることです。

また、現在行っていることの代わりに、適切な CSV パーサーを使用します: http://ostermiller.org/utils/CSV.html

于 2010-04-07T14:53:48.253 に答える
1

Code2 は、呼び出すたびに(既存のオブジェクトに加えて)新しいインスタンスを作成しているため、実際には Code1 よりも効率的ではありません。これは、オブジェクト作成のオーバーヘッドにより、スペースと時間の面で効率が低下します。stringBuilder.toString()java.lang.StringStringBuilder

の内容を にreadLine()直接割り当ててからString分割するStringと、通常は十分なパフォーマンスが得られます。Scannerクラスの使用を検討することもできます。

メモリ節約のヒント

入力で複数の繰り返しトークンに遭遇した場合は、String.intern() を使用して、各同一トークンが同じ String オブジェクトを参照するようにすることを検討してください。例えば

String[] tokens = parseTokens(line);
for (String token : tokens) {
  // Construct business object referencing interned version of token.
  BusinessObject bo = new BusinessObject(token.intern());
  // Add business object to collection, etc.
}
于 2010-04-07T14:52:29.907 に答える
0

StringBuilder にはいくつかの優れた点があります

  • StringBuffer の操作は同期されますが、StringBuilder は同期されません。そのため、StringBuilder を使用すると、シングル スレッドのシナリオでパフォーマンスが向上します。
  • バッファが拡張されると、オブジェクトで setLength(0) を呼び出すことによってバッファを再利用できます。興味深いことに、デバッガーにステップインして StringBuilder の内容を調べると、setLength(0) を呼び出した後でも内容がまだ存在していることがわかります。JVM は文字列の先頭のポインタをリセットするだけです。次回、文字の追加を開始すると、ポインターが移動します
  • 文字列の長さがよくわからない場合は、StringBuilder を使用することをお勧めします。これは、バッファーが拡張されると、同じバッファーを再利用して小さいサイズまたは同じサイズにすることができるためです。

StringBuffer と StringBuilder は、StringBuffer が同期され、StringBuilder が同期されないことを除いて、すべての操作でほぼ同じです。

マルチスレッドがない場合は、StringBuilder を使用することをお勧めします

于 2010-04-07T16:47:50.967 に答える
0

StringBuilderは通常、次のように使用されます。

StringBuilder sb = new StringBuilder();
sb.append("You").append(" can chain ")
  .append(" your ").append(" strings ")
  .append("for better readability.");

String myString = sb.toString(); // only call once when you are done
System.out.prinln(sb); // also calls sb.toString().. print myString instead
于 2010-04-07T15:09:29.517 に答える