자바는 문자열 자료형 클래스로 String, StringBuffer, StringBuilder 이 3가지 자료형을 지원합니다.
이 세 가지 클래스의 차이점을 알아보고, 어느 상황에서 어느 자료형을 사용하는 것이 이상적이고, 성능적으로 우수한지 정리해 봅시다.
StringBuffer / StringBuilder 클래스
StringBuffer / StringBuilder 클래스는 문자열을 연산( 추가 혹은 변경 ) 할 때 주로 사용하는 자료형입니다.
물론 String 자료형도 + 연산이나 concat() 메서드로 문자열을 이어 붙일 수 있습니다.
→ 하지만 덧셈(+) 연산자를 통해 문자열을 결합하면, 내용이 합쳐진 새로운 String 인스턴스를 생성하게 되어 문자열을 많이 결합할수록 공간 낭비뿐 아니라 속도까지 매우 느려진다는 단점이 있습니다.
그래서 자바는 이러한 문자열 연산 전용을 위한 자료형을 따로 제공하는데, 그게 바로 StringBuffer 클래스입니다.
StringBuffer 클래스는 내부적으로 버퍼(buffer)라는 독립적인 공간을 가지게 되어 문자열을 바로 추가할 수 있어 공간낭비를 줄여주며 속도도 매우다는 장점을 가지고 있습니다.
기본적으로 StringBuffer의 버퍼(데이터공간) 크기의 기본값은 16개의 문자를 저장할 수 있는 크기로, 생성자를 통해 크기를 별도로 설정할 수도 있습니다.
문자열 연산 중 할당된 버퍼의 크기를 넘게 되면 자동으로 버퍼를 증강시키게 됩니다. 하지만 효율이 떨어질 수 있으니 버퍼의 크기는 넉넉하게 설정하는 것이 좋습니다.
StringBuffer sb = new StringBuffer(); // 기본 16 버퍼 크기로 생성
// sb.capacity() - StringBuffer 변수의 배열 용량의 크기 반환
System.out.println(sb.capacity()); // 16
sb.append("1111111111111111111111111111111111111111"); // 40길이의 문자열을 append
System.out.println(sb.capacity()); // 40 (추가된 문자열 길이만큼 늘어남)
StringBuffer 내장 메서드
| 메서드 | 설 명 |
| StringBuffer() | 버퍼의 길이를 지정하지 않으면 크기가 16인 버퍼 생성 |
| StringBuffer(int length) | length 길이를 가진 StringBuffer 클래스의 인스턴스(buffer)를 생성 |
| StringBuffer(String str) | 지정한 문자열( str )의 길이보다 16만큼 더 큰 버퍼를 생성 |
| StringBuffer append(boolean b) StringBuffer append(char c) StringBuffer append(char[ ] str) StringBuffer append(double d) StringBuffer append(float f) StringBuffer append(int i) StringBuffer append(long l) StringBuffer append(Object obj) StringBuffer append(String str) |
매개변수로 입력된 값을 문자열로 변환하여 StringBuffer 인스턴스가 저장하고 있는 문자열의 뒤에 덧붙임 |
| int capacity( ) | StringBuffer 인스턴스의 버퍼크기 반환 (자료형의 할당된 크기를 반환) |
| int length( ) | StringBuffer 인스턴스에 저장된 문자열의 길이 반환 (버퍼에 담긴 문자열 데이터를 반환) |
| char charAt(int index) | 지정된 위치( index )에 있는 문자를 반환 |
| StringBuffer delete(int start, int end) | 시작위치( start )부터 끝 위치( end )사이에 있는 문자를 제거 단, end 위치의 문자는 제외(start <= x < end) |
| StringBuffer deleteCharAt(int index) | 지정된 위치( index )의 문자를 제거 |
| StringBuffer insert(int pos, boolean b) StringBuffer insert(int pos, char c) StringBuffer insert(int pos, char[ ] str) StringBuffer insert(int pos, doule d) StringBuffer insert(int pos, float f) StringBuffer insert(int pos, int i) StringBuffer insert(int pos, long l) StringBuffer insert(int pos, Object obj) StringBuffer insert(int pos, String str) |
두 번째 매개변수로 받은 값을 문자열로 변환하여 지정된 위치( pos )에 추가 ( pos 는 0부터 시작) |
| StringBuffer replace(int start, int end, String str) |
지정된 범위( start ~ end )의 문자들을 주어진 문자열로 바꾼다. 단, end 의 위치는 범위에 포함되지 X (start <= x < end) |
| StringBuffer reverse( ) | StringBuffer 인스턴스에 저장되어 있는 문자열의 순서를 거꾸로 나열 |
| void setCharAt(int index, char ch) | 지정된 위치( index )의 문자를 주어진 문자( ch )로 바꾼다. |
| void setLength(int newLength) | 지정된 길이로 문자열의 길이를 변경 길이를 늘리는 경우에는 나머지 빈공간들을 널문자( \u0000 )로 채운다. |
| String toString( ) | StringBuffer 인스턴스의 문자열을 String 으로 변환 |
| String substring(int start) String substring(int start, int end) |
지정된 범위 내의 문자열을 String 으로 뽑아서 반환 (시작위치( start )만 지정하면 시작위치부터 끝까지 뽑아서 반환) |
* StringBuffer 클래스와 StringBuilder 클래스의 메서드 사용법은 동일합니다.
String vs (StringBuffer, StringBuilder) 비교
문자열 자료형의 불변과 가변
String은 불변
기본적으로 자바에서 String 객체의 값은 변경할 수 없습니다.
한번 할당된 공간이 변하지 않기에 '불변' 자료형 이라고도 불립니다.
그래서 초기공간과 다른 값에 대한 연산에서 많은 시간과 자원을 사용하게 된다는 특징이 있습니다.
문자열이 변경되는 것처럼 생각 될 수도 있지만 해당 메서드 수행 시 또 다른 String 객체를 생성하여 리턴할 뿐입니다.
[ 자바 언어에서 String을 불변으로 설정한 이유 ]
String 객체를 불변하게 설계한 이유는 캐싱, 보안, 동기화, 성능측면 이점을 얻기 위해서입니다.
1. 캐싱 : String을 불변하게 함으로써 String pool에 각 리터럴 문자열의 하나만 저장하며 다시 사용하거나 캐싱에 이용가능하며 이로 인해 힙 공간을 절약할 수 있다는 장점이 있습니다.
2. 보안 : 예를 들어 데이터베이스 사용자 이름, 암호는 데이터베이스 연결을 수신하기 위해 문자열로 전달되는데, 만일 번지수의 문자열 값이 변경이 가능하다면 해커가 참조 값을 변경하여 애플리케이션에 보안 문제를 일으킬 수 있습니다.
3. 동기화 : 불변함으로써 동시에 실행되는 여러 스레드에서 안정적이게 공유가 가능합니다.
StringBuffer / StringBuilder는 가변
StringBuffer나 StringBuilder의 경우 문자열 데이터를 다룬다는 점에서 String 객체와 같지만, 객체의 공간이 부족해지는 경우 버퍼의 크기를 유연하게 늘려주어 가변적이라는 차이점이 있습니다.
두 클래스는 내부 Buffer( 데이터를 임시로 저장하는 메모리 )에 문자열을 저장해 두고 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있습니다.
따라서 값이 변경될 때마다 새롭게 객체를 만드는 String보다 훨씬 빠르기 때문에, 문자열의 추가, 수정, 삭제가 빈번하게 발생할 경우 StringBuffer / StringBuilder를 사용하는 것이 이상적이라 말할 수 있습니다.
문자열 자료형의 값 비교
String 값 동등 비교
String 객체는 간단하게 equals() 메서드를 통해 비교가 가능합니다.
StringBuffer / StringBuilder 값 동등 비교
toString()으로 String객체로 변환한 후 equals()로 비교해야 합니다.
문자열 자료형의 성능 비교
문자열 합치기 성능
문자열 연산이 많은 경우 아예 처음부터 StringBuilder() 객체로 문자열을 생성한 후 사용하는 것 이 성능적으로 우수합니다.
성능상에서 자료형 선택 결론
많은 양의 문자열 수정을 필요로 하는 경우 StringBuffer / StringBuilder 클래스를,
단순 조회 연산에는 String 클래스가 크기가 고정되어 있어 더 빠르게 읽을 수 있습니다.
StringBuffer / StringBuilder 차이점
둘은 가변적인 특성과 제공 메서드까지 똑같으며 사용법 또한 같습니다.
둘의 차이점이 있다면 바로 멀티 스레드에서의 안정성의 차이라고 할 수 있습니다.
스레드(Thread)의 안정성
▶ StringBuffer 클래스는 스레드에서 안전합니다. ( thread safe )
▶ StringBuilder 클래스는 쓰레드에서 불안전합니다. ( thread unsafe )
두 클래스는 동기화에서의 지원 유무가 다릅니다.
StringBuilder는 동기화를 지원하지 않는 반면, StringBuffer는 동기화를 지원하기에 멀티 스레드 환경에서도 안전하게 동작하게 됩니다.
그 이유는 StringBuffer는 메서드에서 synchronized 키워드를 사용하기 때문입니다.
※ java에서 synchronized 키워드는 여러 개의 스레드가 한 개의 자원에 접근하려고 할 때, 현재 데이터를 사용하고 있는 스레드를 제외하고 나머지 스레드들이 데이터에 접근할 수 없도록 막는 역할을 수행합니다.
result ) web이나 소켓환경 같이 비동기로 동작하는 경우가 많을 땐 StringBuffer를 사용하는 것이 안전합니다.
순수 성능 비교
기본 성능은 StringBuilder 클래스가 우월합니다. → 안정성을 덜 따진 채 연산하기 때문에 당연히 더 빠를 수밖에 없습니다.
만약 싱글 스레드 환경에서나 비동기를 사용할 일이 없다면, StringBuilder를 쓰는 것이 이상적이라 할 수 있습니다.
하지만 현업에서는 자바 애플리케이션을 대부분 멀티 스레드 이상의 환경에서 돌아가기 때문에 웬만하면 안정적인 StringBuffer로 통일하여 코딩하는 것이 좋습니다.
[ 참고 자료 ]
'Java' 카테고리의 다른 글
| [Java] 출력문 println, printf (0) | 2023.09.14 |
|---|---|
| [Java] 중복 키 허용 MultiValueMap 와 HashMap 차이 (0) | 2023.08.29 |
| [ Java ] HTML 화면 캡쳐 후 Server 스토리지에 PDF 저장하는 방법 (0) | 2023.04.26 |
| [Java] Collection 정리 (0) | 2023.04.23 |
| JVM ( Java Virtual Machine ) (0) | 2023.04.06 |



댓글