LoginSignup
1
1

More than 3 years have passed since last update.

StringBuilder を使うより足し算を使ったほうが速い例(Java)

Last updated at Posted at 2019-04-27

Java で、文字列を連結する際には足し算ではなく StringBuilder を使ったほうが速い、という話はよく聞くけど、そうじゃないこともあるよ。という例。

コメントを頂いたとおり、初出時ひどく間違っていました。すいません。初出時のコードで条件を揃えても差が出ませんでしたので、差が出るような条件に変更しました。

実行環境

$ java --version
openjdk 12 2019-03-19
OpenJDK Runtime Environment (build 12+33)
OpenJDK 64-Bit Server VM (build 12+33, mixed mode, sharing)
$ javac --version
javac 12

サンプルコード1

UseStringBuilder

UseStringBuilder.java
public class UseStringBuilder {
  private static int receiver(String s) {
    if (s.equals("hoge")) {
      return 1;
    } else {
      return 0;
    }
  }

  private static final String foo = "uprjkdowvyvqxlncsjgqzstikgclvgorshfrruifnnuzcfqtgtojfqsakcfvaisaysaxbrlpfczukomfxoebwypmqbkqmeevgivpdxnawthcazjobhhhydlbeiltwbmvwsykslyudqludjqlmkzilhreuxyajqgpiwebbxdnccrfmictdxolowxxnaeoucmtybdnmujrwshdezptpjpmzjdnasikhjztfnuezvipxwvywhgvmzqtrfehkkbrgganygop";
  private static final String bar = "bjsqdbkweettnvympybihyjrkhqtedvpogounxelthhyrtbpzoldujwzmmspacjtxwjwciusocwimihuumzvarvyqorunyinmqlkaefmlghcoxsvqbbazlbgavsffmqnjyaqturfgvwrfsgdcrksdexcipznpovpzilbgpxewclexahkxylffwsjiuiuthtbkrkqimcfcfzkoptzsroljeagdzgacdpgxdqwnjymwnnvqlohvsyxkbnazgedrxdjukfh";
  private static final String baz = "phblfiycdsnaahcskasevmthowdijgvfxdzuiivsubtqdwqzcbjhxvlhclkxnmpikfphceulcypiukpkrwzrnmzabydgmfwulrkjbonpcfgvjfbewdavycsjaqfsgvuqunblbzysezasrlrkeawotzjmdvemcqfditpjuolntiymrwxbgmhupoznjydqxzhghgifwnbkgosarjtuvxgneqorxzjemqtepwldrmqytkygsfetvnclqhyxoprioatxxkwo";
  private static final String qux = "rysvvsftwtolxonofdvkjjepouyayiyszgehjuqmunagaaiacrlpalcyizpwmrscldwpfiggobbsynzczfjhcqoqmlkvobljithjucwxmyzdsbrhkjpnpezxmqegbllwcdtraovdupkhbnsekkszffesmrpigwaeqqdxtnklusiwyljbhkzhktarxcraqvcvdybpunxeqnurmrbhoptgdffcfwwemqxvivxhgdnyttkivxjfzzhbqgujigmwmetnuxod";
  private static final String quux = "aodwvgukhmcwrzxwpmlucjnnwtjviytbtbahyexaefkmmweozifczxnzxafwbyjgoknssrtrdoihwhxmktsykfgapffmzqujlgtovsikgjwjtzcuxkgmequueqlnjratiqrznxpyomvsyiccbiyqrwbelbhpvvpgscqzpdsnqrohphdiomjcwivxddpyqelcdnapzlixbqdsfrehamzhyaavpuxjklllvulfqyostchdrgjgdbugfoeuknbsbrntkevf";

  public static void main(String[] args) {
    int sum = 0;
    String[] bars = new String[] { "baz", "qux" };
    for (int i = 0; i < Integer.parseInt(args[0]); ++i) {
      sum += receiver(new StringBuilder()
      .append("hoge")
      .append( foo )
      .append( bar )
      .append( baz )
      .append( qux )
      .append( quux )
      .toString() );
    }
    System.out.println(sum);
  }
}

UseStringPlus

UseStringPlus.java
public class UseStringPlus {
  private static int receiver( String s ){
    if ( s.equals("hoge") ){
      return 1;
    } else {
      return 0;
    }
  }
  private static final String foo = "uprjkdowvyvqxlncsjgqzstikgclvgorshfrruifnnuzcfqtgtojfqsakcfvaisaysaxbrlpfczukomfxoebwypmqbkqmeevgivpdxnawthcazjobhhhydlbeiltwbmvwsykslyudqludjqlmkzilhreuxyajqgpiwebbxdnccrfmictdxolowxxnaeoucmtybdnmujrwshdezptpjpmzjdnasikhjztfnuezvipxwvywhgvmzqtrfehkkbrgganygop";
  private static final String bar = "bjsqdbkweettnvympybihyjrkhqtedvpogounxelthhyrtbpzoldujwzmmspacjtxwjwciusocwimihuumzvarvyqorunyinmqlkaefmlghcoxsvqbbazlbgavsffmqnjyaqturfgvwrfsgdcrksdexcipznpovpzilbgpxewclexahkxylffwsjiuiuthtbkrkqimcfcfzkoptzsroljeagdzgacdpgxdqwnjymwnnvqlohvsyxkbnazgedrxdjukfh";
  private static final String baz = "phblfiycdsnaahcskasevmthowdijgvfxdzuiivsubtqdwqzcbjhxvlhclkxnmpikfphceulcypiukpkrwzrnmzabydgmfwulrkjbonpcfgvjfbewdavycsjaqfsgvuqunblbzysezasrlrkeawotzjmdvemcqfditpjuolntiymrwxbgmhupoznjydqxzhghgifwnbkgosarjtuvxgneqorxzjemqtepwldrmqytkygsfetvnclqhyxoprioatxxkwo";
  private static final String qux = "rysvvsftwtolxonofdvkjjepouyayiyszgehjuqmunagaaiacrlpalcyizpwmrscldwpfiggobbsynzczfjhcqoqmlkvobljithjucwxmyzdsbrhkjpnpezxmqegbllwcdtraovdupkhbnsekkszffesmrpigwaeqqdxtnklusiwyljbhkzhktarxcraqvcvdybpunxeqnurmrbhoptgdffcfwwemqxvivxhgdnyttkivxjfzzhbqgujigmwmetnuxod";
  private static final String quux = "aodwvgukhmcwrzxwpmlucjnnwtjviytbtbahyexaefkmmweozifczxnzxafwbyjgoknssrtrdoihwhxmktsykfgapffmzqujlgtovsikgjwjtzcuxkgmequueqlnjratiqrznxpyomvsyiccbiyqrwbelbhpvvpgscqzpdsnqrohphdiomjcwivxddpyqelcdnapzlixbqdsfrehamzhyaavpuxjklllvulfqyostchdrgjgdbugfoeuknbsbrntkevf";
  public static void main( String[] args ){
    int sum=0;
    String[] bars = new String[]{ "baz", "qux" };
    for( int i=0 ; i<Integer.parseInt(args[0]) ; ++i ){
      sum += receiver( 
        "hoge"
        + foo 
        + bar 
        + baz 
        + qux 
        + quux 
       );
    }
    System.out.println(sum);
  }
}

走らせる人

run.rb
%w( UseStringBuilder UseStringPlus ).each do |name|
  p name
  puts( %x( javac #{name}.java && time java #{name} 10000000 ) )
end

実行結果

"UseStringBuilder"

real    0m2.594s
user    0m2.488s
sys 0m0.356s
0
"UseStringPlus"

real    0m0.227s
user    0m0.239s
sys 0m0.036s
0

サンプルコード2

コメントを受けて、コンパイル時に結合が行われないようなサンプルでの実験。

UseStringBuilder2

UseStringBuilder2.java
public class UseStringBuilder2 {
  private static int receiver(String s) {
    if (s.equals("hoge")) {
      return 1;
    } else {
      return 0;
    }
  }

  private static String makestr(int len, char c0){
    StringBuilder b = new StringBuilder();
    for( int i=0 ; i<len*1024 ; ++i ){
      b.append(c0+(char)i);
    }
    return b.toString();
  }

  public static void main(String[] args) {
    String foo = makestr(1, args[1].charAt(0));
    String bar = makestr(2, args[1].charAt(0));
    String baz = makestr(4, args[1].charAt(0));
    String qux = makestr(8, args[1].charAt(0));
    String quux = makestr(16, args[1].charAt(0));
    String corge = makestr(32, args[1].charAt(0));
    int sum = 0;
    String[] bars = new String[] { "baz", "qux" };
    for (int i = 0; i < Integer.parseInt(args[0]); ++i) {
      sum += receiver(new StringBuilder()
      .append("hoge")
      .append( foo )
      .append( bar )
      .append( baz )
      .append( qux )
      .append( quux )
      .append( corge )
      .toString() );
    }
    System.out.println(sum);
  }
}

UseStringPlus2

UseStringPlus2.java
public class UseStringPlus2 {
  private static int receiver( String s ){
    if ( s.equals("hoge") ){
      return 1;
    } else {
      return 0;
    }
  }
  private static String makestr(int len, char c0){
    StringBuilder b = new StringBuilder();
    for( int i=0 ; i<len*1024 ; ++i ){
      b.append(c0+(char)i);
    }
    return b.toString();
  }
  public static void main( String[] args ){
    String foo = makestr(1, args[1].charAt(0));
    String bar = makestr(2, args[1].charAt(0));
    String baz = makestr(4, args[1].charAt(0));
    String qux = makestr(8, args[1].charAt(0));
    String quux = makestr(16, args[1].charAt(0));
    String corge = makestr(32, args[1].charAt(0));
    int sum=0;
    for( int i=0 ; i<Integer.parseInt(args[0]) ; ++i ){
      sum += receiver( 
        "hoge"
        + foo 
        + bar 
        + baz 
        + qux 
        + quux 
        + corge
       );
    }
    System.out.println(sum);
  }
}

走らせる人

%w( UseStringBuilder2 UseStringPlus2 ).each do |name|
  p name
  puts( %x( javac #{name}.java && time java #{name} 10000 a ) )
end

実行結果

"UseStringBuilder2"

real    0m1.838s
user    0m1.608s
sys 0m0.450s
0
"UseStringPlus2"

real    0m0.917s
user    0m0.903s
sys 0m0.263s
0

というわけで

というわけで、上記のようなケースでは、足し算で連結したほうが速い。

Java のバージョン等によって逆転したりとか、いろいろあると思う。

1
1
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1