Java/[도서] 자바의 정석

StringBuffer클래스와 StringBuilder클래스

Lea Hwang 2022. 4. 29. 00:55

자바의 정석

Chapter 소제목
9. java.lang패키지와 유용한 클래스 1.1.3 StringBuffer클래스와 StringBuilder클래스

 

 

알고리즘 문제를 풀거나 남들이 적어둔 코드를 보다 보면 문자열을 String이 아닌 StringBuffer 또는 StringBuilder를 사용해서 구현한 것을 볼 수 있었습니다.

 

 

String클래스, StringBuffer클래스, StringBuilder클래스를 비교 분석하면서 관련 메서드까지 정리하는 시간을 가져보도록 하겠습니다.

 


 

StringBuffer클래스

String클래스는 지정된 문자열을 변경할 수 없지만 StringBuffer클래스는 변경이 가능합니다.(mutable)

내부적으로 문자열 편집을 위한 버퍼(buffer)를 가지고 있으며 , StringBuffer인스턴스를 생성할 때 그 크기를 지정할 수 있습니다. 이때 크기를 지정해 주지 않으면 기본적으로 16이 되지만 작업의 효율성을 위해서는 편집할 문자열의 크기를 고려해서 버퍼의 길이를 충분히 잡아주고 시작하는 것을 권장합니다.

 

1. String클래스처럼 StirngBuffer클래스도 문자형 배열 (char[ ])을 내부적으로 가지고 있습니다.

public final class StringBuffer implements java.io.Serialicable {
	private char[] value;
    	...
}

 

2. 배열은 길이 변경이 불가하므로 공간이 부족하면 새로운 배열을 생성해야 합니다.

  • 새로운 배열 생성
  • 내용 복사
  • 참조 변경

 

 

StirngBuffer의 변경

StirngBuffer클래스는 여러 메서드를 통해 내용 변경이 가능합니다. 

    * 생성자와 메서드는 밑에서 더 자세히 다루도록 하겠습니다.

 

그중 append( )의 특징으로는 반환 타입이 StringBuffer로 자신의 주소를 반환한다는 점입니다.

텍스트만 보면 이해가 어려우므로 예제 코드로 설명드리겠습니다.

StringBuffer sb = new StringBuffer("abc");
sb.append("123"); 			// sb의 내용 뒤에 "123"을 추가합니다,

StringBuffer sb2 = sb.append("AA"); 	// sb의 내용 뒤에 "AA"를 추가합니다.
System.out.println(sb); 		// abc123AA
System.out.println(sb2); 		// abc123AA

 

 

StringBuffer의 참조를 반환 = sb와 sb2가 같은 StringBuffer인스턴스를 가리키고 있어 같은 내용이 출력되는 것입니다.

 

따라서 다음과 같이 연속적으로 append( )를 호출하는 것이 가능합니다.

StringBuffer sb = new StringBuffer("abc");
sb.append("123");
sb.append("AA");

↓

StringBuffer sb = new StringBuffer("abc");
sb.append("123").append("AA");

 

StringBuffer의 비교

String클래스에서는 equals메서드를 오버라이딩해서 문자열의 내용을 비교하도록 구현되어 있지만,

StringBuffer클래스는 equals메서드를 오버라이딩하지 않습니다.

StringBuffer인스턴스에 담긴 문자열을 비교하기 위해서는 String으로 변환 후 equals메서드를 통해 비교해야 합니다.

StringBuffer sb = new StringBuffer("ABC");
StringBuffer sb2 = new StringBuffer("ABC");

System.out.println(sb == sb2); 	    // false
System.out.println(sb.equals(sb2)); // false

↓

String s = sb.toString();
String s2 = sb2.toString();

System.out.println(s.equals(s2)); // true

 

 

StringBuffer클래스의 생성자와 메서드

StringBuffer클래스 역시 문자열을 다루기 위한 것이므로 String클래스와 유사한 메서드를 가지고 있습니다.

그리고 StringBuffer는 추가, 변경, 삭제와 같이 저장된 내용을 변경할 수 있는 메서드들이 추가로 제공됩니다.

메서드 / 설명 예제 / 결과
StringBuffer( ) StringBuffer sb = new StringBuffer( );
16문자를 담을 수 있는 버퍼를 가진 StringBuffer 인스턴스를 생성합니다. → char [ ] sb = ""
StringBuffer(int length) StringBuffer sb = new StringBuffer(10);
지정된 개수의 문자를 담을 수 있는 버퍼를 가진 StringBuffer인스턴스르 생성합니다. → char [ ] sb = ""
StringBuffer(String str) StringBuffer sb = new StringBuffer("Hi");
지정된 문자열 값(str)을 갖는 StringBuffer인스턴스를 생성합니다. → char [ ]
sb = "Hi"
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 sb = new StringBuffer("abc");
StringBuffer sb2 = sb.append(true);
sb.append('d').append(10.0f);

StringBuffer sb3 = new StringBuffer("ABC").append(123);
문자열 추가 : 매개변수로 입력된 값을 문자열로 변환하여 StringBuffer에 저장합니다.  sb = "abctrued10.0ABC123"
sb2 = "abctrued10.0ABC123"
sb3 = "abctrued10.0ABC123"

→ 자기자신의 반환 = 3개 참조변수가 모두 StringBuffer객체를 가리키고 있으므로 결과가 같습니다. 
int capacity( ) StringBuffer sb = new StringBuffer(100);
sb.append("abcd");
int bufferSize = sb.capacity();
int stringSize = sb.length();
StringBuffer인스턴스의 버퍼크기를 알려줍니다.
비교 : length( )는 버퍼에 담긴 문자열의 길이를 알려줍니다. 
bufferSize = 100
stringSize = 4

→ sb에 담긴 문자열이 "abcd"이므로 4가 출력됩니다.
char charAt(int index) StringBuffer sb = new StringBuffer("abc");
char c = sb.charAt(2);
지정된 위치(index)에 있는 문자를 반환합니다.  c = 'c'
StringBuffer delete(int start, int end)
StringBuffer sb = new StringBuffer("0123456");
StringBuffer sb2 = sb.delete(3,6);
시작위치(start)부터 끝 위치(end) 사이에 있는 문자를 제거합니다. 단, 끝 위치(end)의 문자는 제외합니다.  sb = "0126"
sb2 = "0126"
StringBuffer deleteCharAt(int index) StringBuffer sb = new StringBuffer("0123456");
sb.deleteCharAt(3);
지정된 위치(index)의 문자 한 개를 제거합니다. sb = "012456"
StringBuffer insert(int pos, boolean b)
StringBuffer insert(int pos, char c)
StringBuffer insert(int pos, char[] str)
StringBuffer insert(int pos, double 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)

StringBuffer sb = new StringBuffer("0123456");
sb.insert(4,'.');
두번째 매개변수로 받은 값을 문자열로 변환하여 지정된 위치(pos)에 추가합니다. pos는 0부터 시작합니다. 
 추가하는 것이지 이미 있는 원소를 지우는 것이 아닙니다. 
지정된 위치(pos)뒤에 있는 원소들은 뒤로 한 칸씩 밀립니다.
sb = "0123.456"
int length( ) StringBuffer sb = ne StringBuffer("0123456");
int length = sb.length();
StringBuffer인스턴스에 저장되어 있는 문자열의 길이를 반환합니다. length = 7
StringBuffer replace(int start, int end, String str) StringBuffer sb = new StringBuffer("0123456");
sb.replace(3, 6, "AB");
치환 : 지정된 범위(start <= x < end)의 문자들을 주어진 문자열(str)로 바꿉니다.  sb = "012AB6"
StringBuffer reverse( ) StringBuffer sb = new StringBuffer("0123456");
sb.reverse();
문자열 뒤집기 : StringBuffer인스턴스에 저장되어 있는 문자열의 순서를 거꾸로 나열합니다. sb = "6543210"
void setCharAt(int index, char ch) StringBuffer sb = new StringBuffer("0123456");
sb.setCharAt(5, 'o');
지정된 위치(index)의 문자를 주어진 문자(ch)로 바꿉니다. sb = "01234o6"
void setLength(int newLength) StringBuffer sb = new StringBuffer("0123456");
sb.setLength(5);

StringBuffer sb2 = new StringBuffer("0123456");
sb2.setLength(10);
String str = sb2.toString().trim();
지정된 길이(newLength)로 문자열의 길이를 변경합니다. 길이를 늘리는 경우 나머지 빈 공간은 null문자로 채웁니다.  sb = "01234"
sb2 = "0123456    "
str = "0123456"
String toString( ) StringBuffer sb = new StringBuffer("0123456");
String str = sb.toString();
StringBuffer인스턴스의 문자열을 String으로 반환합니다. str = "0123456"
String substring(int start)
String substring(int start, int end)
StringBuffer sb = new StringBuffer("0123456");
String str = sb.substring(3);
String str2 = sb.substring(3, 5);
지정된 범위 내의 문자열을 String으로 뽑아서 반환합니다.
만약 시작위치만 정했다면 시작위치부터 문자열 끝까지 뽑아서 반환합니다.
str = "3456"
str2 = "34"

 

앞서 말씀드린 것 처럼 String클래스 메서드와 겹치는 것이 많아 익히는 데 어려움은 없을 것 같습니다. 

그래도 버겁다면 우선 볼드체라도 한 두번 더 눈으로 보시고 사용해보시는 것을 추천합니다.

 

 

 

다음으로 배울 내용은 StringBuilder입니다. 

더 자세한 내용은 13장 쓰레드를 알아야 하므로 기본적인 것만 짚고 넘어가도록 하겠습니다. 

 

 

 StringBuilder란?

StringBuffer와 StringBuilder는 거의 같습니다. 차이점으로는 '동기화'가 되어 있는지 아닌지의 유무입니다.

StringBuffer는 멀티쓰레드에 안전(thread safe)하도록 동기화되어있습니다. 이번 장에서는 이 말의 의미가

동기화가 StringBuffer의 성능을 떨어뜨린다는 것만 이해하시면 충분합니다. 

 

멀티쓰레드로 작성된 프로그램이 아닌 경우, StringBuffer의 동기화는 불필요하게 성능만 떨어뜨리게 됩니다. 

그래서 나온 개념이 StringBuilder입니다. 

 

StringBuffer에서 쓰레드의 동기화만 뺀 개념이 StringBuilder입니다.

메서드는 호환이 가능하므로 만약 StringBuilder로 수정하려면, 간단히 StringBuffer → StringBuilder로 바꾸기만 하면 됩니다.

StringBuffer sb;
sb = new StringBuffer();
sb.append("abc");

↓

StringBuilder sb;
sb = new StringBilder();
sb.append("abc");