기록/JAVA

[JAVA] StringBuilder의 append(), String의 + 연산자 속도차이

5월._. 2022. 3. 11.
728x90

StringBuilder의 append()와 String의 +연산자의 속도차이

자바에서 String은 변경이 안되는 객체이기 때문에 +연산을 하면 내부적으로 새 메모리를 할당받아서 사용한다고 한다. 그래서 String의 변경이 많은 경우에는 StringBuilder를 사용한다. 그런데 이 둘의 속도차이는 대략 어느정도 나는지, 정확히 어떤 부분에서 차이가 발생하는지 궁금해서 테스트해봤다.

테스트코드

초반 tc가 결과값이 좀 튀어서 앞의 두번 정도 계산하지 않고 12번 돌렸다.

출력창의 (final O)표시는 무시해도 된다. 출력창 문자열 지우는걸 깜빡했다. final과 일반 string을 둘다 테스트해봤는데 내 컴퓨터에서는 유의미한 차이가 나지 않아서 코드를 지웠다. 

public static void main(String[] args) {
   long start, end, sbtime = 0, strtime = 0;
   for (int tc = 0; tc < 10; tc++) {
      start = System.nanoTime();
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < 10000; i++) {
         sb.append(i);
      }
      end = System.nanoTime();
      sbtime += (end - start);
      System.out.println("SB append(final O): " + (end - start));


      start = System.nanoTime();
      String str = "";
      for (int i = 0; i < 10000; i++) {
         str = str + i;
      }
      end = System.nanoTime();
      strtime += (end - start);
      System.out.println("String +(final O): " + (end - start));

      System.out.println("======================================");
   }

   System.out.println("SB append avg: " + sbtime / 10);
   System.out.println("String + avg: " + strtime / 10);
}

테스트 코드 결과

굳이 정확하게 계산하지 않아도 StringBuilder와 String연산은 자리수 두세개가 차이난다. 

 

StringBuilder의 append() 실행 순서

StringBuilder의 append()는 이미 [이 글]에서 설명했기때문에 넘어간다.

String의 +연산자 실행 순서

위의 코드 중 str=str+i는 부를 때마다 최초로 StringBuilder() 객체를 만들고, append()함수를 두 번 부른다. 그리고 마지막에 StringBuilder()객체를 toString()을 이용해 new String()을 만든다.

풀어서 생각해보면 이런식이다.

str = new StringBuilder().append(str).append(i).toString();
//StringBuilder.java 

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

그러면 당연히 str=str+i연산은 처음부터 StringBuilder만을 이용해서 연산하는 것과 비교해서 (객체생성시간+toString()시간)*반복수만큼 차이가 나게된다. 

 

결론

String은 java에서 최적화를 시킨 덕분에 현재는 +연산을 할 때마다 새로 메모리가 생성되지는 않지만, 빠른 연산을 위해서 StringBuilder 객체를 생성하므로 그 시간을 항상 염두해두어야한다. 모두 append한 뒤에는 toString()메서드로 새 String을 생성하는 것도 알아두면 좋을 것 같다.

댓글