-
[Java ] String, Stringbuffer, Stringbuilder의 차이 및 장단점(+속도 비교)Java 2021. 11. 9. 02:06
개요
Java에서 문자열을 다루는 대표적인 클래스로 String, StringBuffer, StringBuilder가 있습니다.
연산이 많지 않을 때는 어떤 클래스를 사용하여도 크게 문제가 없으나 연산 횟수가 많아지거나 멀티스레드, Race condition 등이 자주 발생한다면 각 클래스의 특징을 이해하고 상황에 맞는 적절한 클래스를 사용해야 합니다.
Race condition이란?
두 개의 쓰레드가 하나의 자원을 놓고 서로 사용하려고 경쟁하는 상황을 말합니다.
String은 불변(immutable)하다.
String이 StinrgBuffer/StringBuilder 클래스와 가장 큰 차이점은 String은 불변(immutable)의 속성을 갖는다는 점입니다.
String str = "hello"; //String str = new String("hello"); str = str + " world"; // hello world
String 클래스의 참조 변수 str이 가리키는 곳에 저장된 "hello"에 "world" 문자열을 더해 "hello world"로 변경된 것처럼 보입니다.
하지만 사실 기존에 가지고 있던 "hello"는 Garbage로 남아있다가 GC에 의해 사라지게 되고 String클래스의 참조변수 str은 "hello world"라는 값을 가지고 있는 새로운 메모리 영역을 가리키게 변경이 됩니다.
String은 immutable 하기 때문에 문자열을 수정하는 시점에 새로운 String 인스턴스가 탄생하게 됩니다.
이러한 이유로 String을 조작하는 연산은 시간과 자원(메모리)을 사용하고 문자열의, 추가, 삭제, 수정 등의 연산이 빈번하게 발생하는 알고리즘에 String 클래스를 사용하면 Heap에 많은 Garbage가 생성되어 애플리케이션 성능에 악역향을 끼칠 수 있습니다.
StringBuilder와 StringBuffer
String과는 반대로 가변성을 가지기 때문에. append(),. delete() 등의 API를 이용하여 동일 객체 내에서 문자열을 변경하는 것이 가능합니다.
즉 문자열을 추가, 수정, 삭제가 빈번하게 발생할 경우라면 String클래스가 아닌 StringBuilder/StringBuffer를 사용해야 합니다.
StringBuilder vs StringBuffer
그렇다면 StringBuilder와 StringBuffer의 차이는 무엇일까요?
StringBuilder의 경우 동기화를 보장하지 않지만 StringBuffer의 경우 동기화를 보장합니다.
Stringbuilder는 동기화를 지원하지 않기 때문에 멀티스레드 환경에서 사용하는 것은 적합하지 않지만 동기화를 고려하지 않는 만큼 단일 스레드에서의 성능은 StringBuffer 보다 뛰어납니다.
성능 비교
문자열 연산을 하는 코드를 1만 번 수행하여 일정 크기만큼 증가시키며 수행 시간을 측정해 보았을 때 그래프입니다.
String은 연산을 할 때 새로운 문자열 객체를 생성하기 때문에 수행 속도가 매우 느리고
StringBuffer의 경우에는 동기화 기능으로 인해 상대적으로 StringBuilder 보다 느립니다.
정리하자면 String < StringBuffer < StringBuilder 순으로 속도입니다.
String의 최적화
JDK 1.5 버전 이후부터 String의 + 연산은 컴파일 시에 StringBuilder를 사용하도록 자동 변환하는 최적화가 이루어진다고 알려져 있습니다.
그러면 우리는 String을 그냥 사용하면 되는 것일까요?
예제 1) 한 줄로 모두 선언한 경우
//컴파일 전 소스코드 String str1 = "0" + "1" + "2"; //컴파일 이후, 디컴파일 한 소스코드 String str1= "012";
한줄로 모두 선언한 경우에는 하나의 String으로 성능 최적화가 잘 보이는 모습을 보입니다. 이런 경우에는 굳이 StringBuilder나 StringBuffer를 사용할 필요가 없습니다.
예제 2) 반복문 안에서 선언한 경우
//컴파일 전 소스코드 String str = ""; for(int i=0; i<3; i++){ str += i; } //컴파일 이후, 디컴파일한 소스코드 String str = ""; for(int i=0; i<3; i++){ str = (new StringBuilder()).append(str).append(i).toStirng(); }
반복문 안에서 연산을 수행하는 경우에 반복수행마다 새로운 StringBuilder를 생성하여 성능 저하가 발생하게 됩니다. 이런 경우에는 StringBuilder 또는 StringBuffer를 사용하여 성능 최적화를 해야 합니다.
결론
결과만 보면 StringBuilder를 사용하는 것이 좋아 보이며, 하지만 같이 개발하는 동료 또는 개인의 취향에 따라 어떤 코드에서는 단순히 + 연산자를 이용하는 것이 더 보기 좋을 수도 있습니다.
하지만 반복문을 이용하게 된다면 성능 저하가 발생할 수 있기 때문에 꼭 StringBuilder를 사용해야 합니다.
출처
https://ifuwanna.tistory.com/221
https://madplay.github.io/post/difference-between-string-stringbuilder-and-stringbuffer-in-java
https://siyoon210.tistory.com/160
'Java' 카테고리의 다른 글
[Java] Code Convention(코드 컨벤션) (0) 2021.11.10 [Java] StringTokenzier 와 split 의 차이 (0) 2021.11.10 [Java] 공식문서 보는 법 (0) 2021.11.07 [Java] 자바 컬렉션 프레임워크(Java Collections Framework) (0) 2021.11.07 [Java] Scanner 와 BufferedReader의 차이점 (0) 2021.11.05