Java

String 과 StringBuilder 의 속도차이

dev-jo 2021. 7. 9. 23:54

오늘 문뜩 궁금한 게 생겼다..

 

분명 지나가다가 자바 X 버전 이상부터는

 

String += (opreator)의 성능이 향상되어 속도가 빨라져서 Builder를 쓰지 않아도 된다는 글을 본 거 같았다.

 

궁금한 김에 자료를 찾아보았는데..

 

https://schneide.blog/2009/02/23/about-string-concatenation-in-java-or-dont-fear-the/

 

About String Concatenation in Java or “don’t fear the +”

When it comes to string concatenation in Java many people have almost religious views about performance and style. Sadly, there are some misconceptions and misinformation especially about the perfo…

schneide.blog

 

자바 1.6 이상부터는 컴파일러가 StringBuilder로 컴파일해준다고 적혀있다..

 

하지만 내가 테스트했을 경우에는 속도가 너무 차이가 났다

 

코드를 봐보자..

 

public class StringSpeed {

    public static void main(String[] args) {

        String a = "";

        long stringStart = System.currentTimeMillis();

        for(int i=0; i<100000; i++) {
            a += i;
        }

        long stringEnd = System.currentTimeMillis();

        System.out.println(stringEnd - stringStart);


        StringBuilder builder = new StringBuilder();

        long builderStart = System.currentTimeMillis();

        for(int i=0; i<100000; i++) {
            builder.append(i);
        }

        long builderEnd = System.currentTimeMillis();

        System.out.println(builderEnd - builderStart);

    }

}

 

StringBuilder와 String += 의 속도를 측정하는 코드이다

 

결과는 아래와 같이 나온다.

 

결과물

 

너무 확연하게 차이가 나는 것이다. 

 

너무 궁금한 나머지 

 

프로그래밍을 하시는 지인에게 여쭤보니

 

컴파일된 소스를 까 봐야 알 거 같은데..

 

 

음.. 그럼 class 파일을 디컴파일 시켜보자

 

 

 

import java.io.PrintStream;

public class StringSpeed
{
  public static void main(String[] args)
  {
    String a = "";

    long stringStart = System.currentTimeMillis();

    for (int i = 0; i < 100000; i++) {
      a = new StringBuilder().append(a).append(i).toString();
    }

    long stringEnd = System.currentTimeMillis();

    System.out.println(stringEnd - stringStart);

    StringBuilder builder = new StringBuilder();

    long builderStart = System.currentTimeMillis();

    for (int i = 0; i < 100000; i++) {
      builder.append(i);
    }

    long builderEnd = System.currentTimeMillis();

    System.out.println(builderEnd - builderStart);
  }
}

 

위 소스는 디컴파일된 소스이다

 

컴파일 전 소스와 비교해보면

 

 

 

 for(int i=0; i<100000; i++) {
            a += i;
 }
 
 for (int i = 0; i < 100000; i++) {
      a = new StringBuilder().append(a).append(i).toString();
 }

 

차이가 보인다.

 

String 은 immutable객체이다

 

immutable 링크 에서 확인할 수 있다.

 

immutable 이기 때문에

 

매번 새롭게 객체를 할당해 주어야 하고

 

for 문 안에서 new StringBuilder(); 

 

StringBuilder의 객체를 매번 생성해주기 때문에

 

미리 생성을 해둔 StringBuilder 보다 속도가 느리게 된다.

 

 

 

++  추가 ++

 

public class SpringImmutable { // 컴파일전

    public static void main(String[] args) {

        String str = "0" + "1" + "2";

        String str2 = "";

        str2 += 1;

        str2 += 2;

        str2 += 3;
	}
}

public class SpringImmutable // 컴파일후 디컴파일
{
  public static void main(String[] args)
  {
    String str = "012";

    String str2 = "";

    str2 = new StringBuilder().append(str2).append(1).toString();

    str2 = new StringBuilder().append(str2).append(2).toString();

    str2 = new StringBuilder().append(str2).append(3).toString();
  }
}

 

 

String 을 += 해주면 매번 StringBuilder 를 생성해준다.!

 

 

 

결론

 

1. Compiler는 String을 StringBuilder로 변경해준다.

 

2. 문자열이 가변적이면 StringBuilder를 미리 선언해두고 사용하자.