Java

[Java] String StringBuffer StringBuilder 비교

ziwookim 2022. 10. 15. 00:59

Java에서 문자열을 다루는 대표적인 클래스로는

String, StringBuffer, StringBuilder

가 있다.

 

연산이 많지 않을 때는 어떤 것을 사용하더라도 이슈가 발생할 가능성은 거의 없으나, 연산횟수가 많아지거나 멀티쓰레드, Race condition  등의 상황이 자주 발생하는 경우, 각 클래스의 특징을 이해하고 상황에 맞는 적절한 클래스를 사용해야 한다.

 

String vs StringBuffer, StringBuilder

String과 StringBuffer, StringBuilder 의 가장 큰 차이점은 String은 불변(immutable)의 속성을 갖는다는 점이다.

String str = "hello"; // ①
str = str + " world"; // ②

①에서 "hello" 값을 갖고 있던 String 클래스의 참조변수 str이 가리키는 곳에 ②를 통해 " world" 문자열을 더해 "hello world"로 변경된 것으로 착각할 수도 있다.

하지만, 단순히 값이 변경되는 것이 아니라, 기존에 ①에서 "hello" 값이 저장되어 있던 String 클래스의 참조변수 str이 ②연산을 통해 "hello world"라는 값을 가진 새로운 메모리 영역을 가리키도록 변경되고, 처음 선언된 "hello" 값이 저장되어 할당된 메모리 영역은 Garbage로 남아 있다가 GC(Garbage Collection)에 의해 사라지게 된다.

* String 클래스는 불변하기 떄문에 문자열을 수정하는 시점에 새로운 String 인스턴스가 생성된다.

위와 같이 String은 불변(immutable)의 성질을 갖고 있기 때문에, 변하지 않는 문자열을 자주 읽어 들이는 경우에는 String을 사용하면 좋은 성능을 기대할 수 있다.

 

 그러나, 문자열 연산(추가/수정/삭제)이 빈번하게 발생하는 알고리즘에서는 String 클래스를 사용하면 힙(Heap) 메모리에 많은 임시 Garbage가 생성 되어 힙 메모리 부족으로 어플리케이션 성능에 치명적인 영향을 끼칠 수 있다.

 

이를 해결하기 위해 Java에서는 가변(mutable)성을 가진 StringBuffer / StringBuilder 클래스를 도입했다.

String 과는 상반 되게 가변성을 가진 StringBuffer / StringBuilder는 .append(), .delete() 등의 메소드를 이용해 동일 객체내에서 문자열을 변경하는 것이 가능하다. 따라서 문자열의 연산(추가/수정/삭제)가 빈번하게 발생할 경우라면 String이 아닌, StringBuffer/StringBuilder를 사용하는 것이 합리적이다.

StringBuffer sb = new StringBuffer("hello"); // ①
sb.append(" world"); // ②

 

StringBuffer vs StringBuilder

그렇다면 동일한 api를 지닌 StirngBuffer와 StringBuilder의 차이점은 무엇일까?

가장 큰 차이점은 동기화의 유무로, StringBuffer는 동기화 키워드르 지원하여 멀티 쓰레드 환경에서 안전하다(thread-safe)는 점이다.

참고로 String 또한 불변성을 가졌기 때문에 마찬가지로, 멀티 쓰레드 환경에서의 안정성(thread-safe)을 보장한다.

 

반대로, StringBuilder는 동기화를 지원하지 않기 때문에, 멀티 쓰레드 환경에서 사용하는 것은 적합하지 않지만, 동기화를 고려하지 않는만큼 단일 쓰레드에서의 성능은 StringBuilder가 StringBuffer보다 뛰어나다.

 

요약

컴파일러에서 분석할 때, 최적화에 따라 성능이 달라질 수도 있지만 일반적으로 아래와 같은 경우에 맞게 사용하면 된다.

  • String : 문자열 연산이 적고, 멀티 쓰레드 환경일 경우
  • StringBuffer : 문자열 연산이 많고, 멀티 쓰레드 환경일 경우
  • StringBuilder : 문자열 연산이 많고, 단일 쓰레드이거나, 동기화를 고려하지 않아도 되는 경우

 

출처: https://ifuwanna.tistory.com/221