본문 바로가기
Java/String

[Java] String +연산과 StringBuffer, StringBuilder

by wone_yam 2024. 1. 18.

자바를 공부하거나 프로그래밍할 때 String은 비용(Cost)이 높아! 라는 말을 들어본 적이 있을 거다.

 

혹은 백준, 프로그래머스 문제를 풀다 보면 String으로 문제를 풀었을 땐 시간초과가 나거나 통과가 되지 않는다.

 

하지만 StringBufferStringBuilder를 이용하면 문제가 풀리는 경험을 한 적이 있을 거다.

바로 알아봅시다~!

 

[Java/String] - [Java] String 클래스와 ==, equals의 차이점

 

String에 대해선 위의 글 읽어보기~!

1. + 연산자를 통한 문자열 합치기

String 클래스의 + 연산자는 어떻게 동작할까?

String str = "Hello";  
str += " Java!";

 

JDK 5버전부터 StringBuilder가 추가되면서 String의 +연산의 성능 이슈를 해결하려고 자바에서 많은 노력을 했다.

 

사실 이전에 +를 통한 문자열 합치기는

String str = "Hello";  
str += " Java!";  

str = new String("Hello Java!"); // 이전에는 새로운 String 객체를 생성하는 방식을 썻다.

 

+연산자를 통한 연산은 새로운 String 객체를 만들어서 반환했다.

 

값이 더해지기 전의 str객체는 str += "Java!"; 를 수행하면서 새로운 주소와 "Hello Java!" 라는 값을 얻게 된다.

앞서 말했지만 자바는 String의 + 연산 성능 이슈를 해결하고자

String str = "Hello";  
str += " Java!";  

String str = new StringBuilder("Hello").append(" Java!").toString();

String 객체를 생성하지 않고 StringBuilder 객체를 생성한 후 append 메서드를 이용하여 문자열을 추가한 뒤,


toString을 통해 반환하는 방식으로 변경되었다.

 

이로써 + 연산을 통한 성능 이슈는 해결이 되어서 굳이 StringBuilder, StringBuffer를 사용하지 않아도 된다.

2. String vs StringBuffer vs StringBuilder

하지만 `반복적인` + 연산을 통한 문자열 합치기는 성능 저하를 일으킬 수 있다.

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

for (int i = 0; i < 1000000; i++) {  
    string += "abcde";  
}  

for (int i = 0; i < 1000000; i++) {  
    stringBuffer.append("abcde");  
}  

for (int i = 0; i < 1000000; i++) {  
    stringBuilder.append("abcde");  
}

 

각 for문을 기준으로 각각 ms단위로 실행 시간을 측정해 본 결과

 

 

+연산을 통한 시간이 385154 ms로 6분이 넘는 시간이 걸렸다. (실제로 Test결과본다고 6분동안 모니터 멍하니 보고 있었다.)
그에 반해 Buffer는 11000배 정도 차이가 났고, Builder는 15000배 차이가 났다.
확연한 성능 차이를 볼 수 있다. 계속해서 new를 통한 객체를 생성하길 반복하기 때문에 이런 결과가 나온 거 같다.

결과상 Buffer와 Builder도 차이를 조금은 보이는 거 같은데 무슨 차이가 있는 걸까?

3. StringBuffer vs StringBuilder

결론적으로 두 클래스의 기능적인 차이는 없지만 StringBufferThread-Safe를 해준다.

StringBuffer 클래스 내부를 뜯어서 설명을 읽어보자.

 

 

요약하자면 StringBuilder와 메서드와 기능적인 부분의 차이는 없고, 동일하다 하지만 StringBuffer는 다중스레드에서 사용 시 스레드 안전 즉, 동기화를 보장한다는 말이다.

 

그래서 동일한 작업을 수행하지만 StringBuilder는 동기화를 보장하지 않기 때문에 수행속도가 빠르고 StringBuilder는 단일 스레드에서 사용되게 디자인되었다. 라고 되어 있다.

 

 

실제로 StringBuffer 내부를 보면 모든 메서드가 synchronized 키워드를 포함하여 선언되어 있다.

4. 결론

  1. 지금 우리가 프로그래밍하는 환경에서 +연산에 대한 성능 이슈는 해결이 되었지만 반복적인 String 연산을 할 경우 성능 저하를 일으킨다. 그래서 StringBuffer와 StringBuilder를 사용하면 된다.
  2. 다중 스레드 환경 혹은 스레드 안전이 보장되는지 잘 모를 경우는 StringBuffer를 사용하여 동기화를 보장받자.
  3. 싱글스레드 환경이거나 스레드 안전이 보장이 된다면 StringBuffer보다 성능이 좋은 StringBuilder를 사용하자.

Reference

'Java > String' 카테고리의 다른 글

[Java] String 클래스와 ==, equals의 차이점  (0) 2024.01.16