본문 바로가기
Programming/Java, Spring

StringBuilder와 String 클래스의 문자열 만드는 효율 차이

by Renechoi 2023. 6. 21.

Java 문자열 연결 

 

Java에서 문자열을 연결하는 방식으로 3가지 방법을 사용할 수 있다. 

 

- String을 "+" 연산자로 연결하기 

- StringBuffer 클래스의 append() 메서드를 이용하기

- StringBuilder 클래스의 append() 메서드를 이용하기 

 

각각의 방법은 다음과 같다. 

 

1. String을 "+" 연산자로 연결하기 

final String testWord = "hello";
String string = new String();
string += testWord;

 

 

2. StringBuffer 클래스의 append() 메서드를 이용하기

StringBuffer stringBuffer = new StringBuffer();
final String testWord = "hello";
stringBuffer.append(testWord);

 

 

3. StringBuilder 클래스의 append() 메서드를 이용하기

StringBuilder stringBuilder = new StringBuilder();
final String testWord = "hello";
stringBuilder.append(testWord);

 

 

위의 각각의 방법들을 1만번 반복하는 반복문을 돌렸을 때 실제적인 성능 차이가 어떻게 나는지 살펴보자. 

 

첫 번째 방식 

start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
   string += testWord;
}
end = System.nanoTime();
System.out.println((end - start) / 1000000.0 + " msecs");

 

두 번째 방식

start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
   stringBuffer.append(testWord);
}
end = System.nanoTime();
System.out.println((end - start) / 1000000.0 + " msecs");

 

 

세 번째 방식

start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
   stringBuilder.append(testWord);
}
end = System.nanoTime();
System.out.println((end - start) / 1000000.0 + " msecs");

 

수행 시간의 차이 

 

각각의 수행 시간은 다음과 같다. 

 

 

 

String 객체를 사용하는 첫 번째 방식과 StringBuilder를 사용하는 세 번째 방식은 거의 30배에 가까운 차이가 나는 것을 확인할 수 있다. 

 

반복문 횟수를 10만으로 올리면 그 차이는 더욱 극심해진다. 

 

 

 

왜 이런 차이가 발생할까? 

 

1. String이 가장 느린 이유

 

String은 불변(immutable) 객체이다. 따라서 문자열을 연결할 때마다 새로운 String 객체를 생성한다.

 

예를 들어, string += testWord에서는 반복문이 실행될 때마다 새로운 String 객체가 생성되며, 이전의 문자열과 새로운 문자열을 병합한 결과를 가지게 된다.

 

이런 과정에서 메모리 할당과 복사 작업이 반복되기 때문에 성능이 저하된다.

 

문자열의 길이가 길어질수록 이러한 작업이 더 많이 발생하게 되어 성능 차이가 커진다.

 

 

 

2. StringBuffer보다 StringBuilder가 빠른이유

 

StringBuffer와 StringBuilder는 가변적인(mutable) 문자열 객체로, 문자열 연결 시 내부 버퍼에 문자열을 추가하고 크기가 필요에 따라 자동으로 조정된다. 둘 다 append() 메서드를 사용하여 문자열을 추가할 수 있다.

 

하지만 StringBuffer는 동기화된 연산을 지원하여 멀티스레드 환경에서 안전하게 사용할 수 있다. 이에 반해 StringBuilder는 단일 스레드 환경에서만 사용되므로 동기화 관련 작업이 필요하지 않다.

 

즉 스레드 사용 방식의 차이이다. 

 

따라서 StringBuffer는 동기화 비용 때문에 단일 스레드 환경에서 StringBuilder에 떨어지는 성능을 보인다. 하지만 둘의 차이는 그렇게 크지 않다고 보며, 스레딩 환경을 어떻게 구성하느냐에 따라 동기화된 연산을 지원하는 StringBuffer가 필요할 때도 있을 것이다.

 

 

 

 

전체 코드 

package basic.string;

public class StringBuilderAndStringDifference {
   public static void main(String[] args) {
      final String testWord = "hello";
      long start;
      long end;

      String string = new String();
      StringBuffer stringBuffer = new StringBuffer();
      StringBuilder stringBuilder = new StringBuilder();

      start = System.nanoTime();
      for (int i = 0; i < 100000; i++) {
         string += testWord;
      }
      end = System.nanoTime();
      System.out.println((end - start) / 1000000.0 + " msecs");

      start = System.nanoTime();
      for (int i = 0; i < 100000; i++) {
         stringBuffer.append(testWord);
      }
      end = System.nanoTime();
      System.out.println((end - start) / 1000000.0 + " msecs");

      start = System.nanoTime();
      for (int i = 0; i < 100000; i++) {
         stringBuilder.append(testWord);
      }
      end = System.nanoTime();
      System.out.println((end - start) / 1000000.0 + " msecs");

   }
}
반응형