1

ループで文字列を作成するプログラムを持っていますが、プログラムが遅すぎます。実行に約 600 ミリ秒かかりますOblig1Test.oppgave7。それをスピードアップするために何ができるでしょうか?

Oblig1.toString:

public static String toString(int[] a, char v, char h, String mellomrom)
{
    String s ="";

    s += v;

    if(a.length != 0)
    {
        for(int i = 0; i < a.length-1; i++)
        {
                s += a[i] + mellomrom; 
        }

        s += a[a.length-1];
    }

    s += h;

    return s;
}

Oblig1Test:

public static int oppgave7()
{
   int[] b = new int[20000];
   long tid = System.currentTimeMillis();
   Oblig1.toString(b,' ',' '," ");
   tid = System.currentTimeMillis() - tid;

  if (tid > 40)
  {
    System.out.println("Oppgave 7: Metoden "
      + "er for ineffektiv. Må forbedres!");
  }
}

public static void main(String[] args) throws IOException
{
   oppgave7();
}
4

4 に答える 4

8

コード内の遅い操作が多くの文字列の連結である場合、 StringBuilderを使用すると多くのメリットが得られる可能性があります。

toStringメソッドを次のように変更することにより、

public static String toString(int[] a, char v, char h, String mellomrom){
    StringBuilder sb = new StringBuilder();
    sb.append(v);
    if(a.length != 0){
        for(int i = 0; i < a.length-1; i++){
                sb.append(a[i]).append(mellomrom); 
        }
        sb.append(a[a.length-1]);
    }
    sb.append(h);
    return sb.toString();
}

私のコンピューターでは、493 ミリ秒から 22 ミリ秒にパスすることができました。

于 2013-09-04T13:33:16.977 に答える
2

まず、変数名は一文字?悪ガキ!:) 意味のある名前を付けてください。費用はかかりません。

次に、Java の文字列は不変です。ステートメント

String concatedString = concatedString + secondString

「concatedString に secondString の値を追加する」という意味ではなく、「concatedString と secondString の値である新しい文字列を作成し、concatedString を破棄して、concatedString 参照が新しい文字列を参照するようにする」という意味です。つまり、 + を使用して文字列を連結するたびに、暗黙的に新しい String オブジェクトが作成されます。

ループ内でオブジェクトを作成すると、非常にコストがかかります。

Java は、StringBuilder や StringBuffer などの変更可能な文字列のセットを提供します (後者はスレッドセーフですが、パフォーマンスは低下します)。代わりにそれらのいずれかを使用してください。

于 2013-09-04T13:37:12.310 に答える
1

はい、これはよくある問題です。

Java の文字列は不変です。つまり、Stringオブジェクトが構築されると、それを変更することはできず、その内容をコピーすることによってすべての操作が行われます。

特定のケースでは、s += vorを実行するs += a[i] + mellomromと、実際にはs文字列の内容が newにコピーされStringBuilder、パーツが連結されてから、Stringout が作成されStringBuilderます。そう、

s += v

になる

s = new StringBuilder(s).append(v).toString();

s += a[i] + mellomrom

になる

s = new StringBuilder(s).append(a[i]).append(mellomrom).toString();

これをループで実行すると、パフォーマンスが大幅に低下します (2 つの新しいオブジェクトの構築、コンテンツの 2 回のコピー)。ループ内で文字列を作成するには、独自のインスタンスを使用します。これにより、インスタンスが 1 つだけになり、反復ごとにStringBuilderそれを に変換する必要がなくなります。String

public static String toString(int[] a, char v, char h, String mellomrom)
{
    StringBuilder sb = new StringBuilder();
    sb.append(v);

    if(a.length != 0)
    {
        for(int i = 0; i < a.length-1; i++)
        {
            sb.append(a[i]).append(mellomrom);
        }
        sb.append(a[a.length-1]);
    }
    sb.append(h);
    return sb.toString();
}
于 2013-09-04T13:39:22.617 に答える