JAVA

StringBuffer

쿠키는고양이 2022. 8. 28. 15:58

 

기존에 사용한 String 과 많이 비슷해 보이지만 다른 StringBuffer 에 대해 정리한다.

 

StringBuffer 란 String 처럼 문자열을 취급하는 클래스이다. 하지만 둘의 차이점은 가변성인가, 불변성인가 라는 큰 차이가 존재한다.

 

1. String과 StringBuffer 의 차이점

우선 결론부터 말하자면 String 불변성(immutable)이며 StringBuffer 가변성(mutable)이다.

즉, 값이 변할 수 있는가 없는가의 차이를 갖는다.

 

아래의 코드를 살펴보자.

                String s1 = "";
		s1 += "Hello";
		s1 += " World";
		s1 += " Welcome";

		System.out.println(s1);
 

위 코드에서 s1은 String 클래스의 인스턴스이다. 이 인스턴스를 이용해 다른 문자열들을 붙여 출력한 내용이다.

하지만 String은 불변성을 가지고 있는데 출력 결과는 변한 것을 볼 수 있다.

중요한 것은 String은 '불변성이면서 완성된 문자열'이라는 것이다.

즉, s1에 마지막 문장인 "Welcom" 이 추가되면서 완성되며 값이 변할수 없는 것이다.

하지만 이 과정에서는 문제가 발생한다. 위의 코드를 실제 내부에서 처리되는 과정대로 풀어보면 다음과 같다.

                s1 = new StringBuffer(s1).append("Hello").toString();
		s1 = new StringBuffer(s1).append(" World").toString();
		s1 = new StringBuffer(s1).append(" Welcome").toString();
                System.out.println(s1);
 

코드에서 보면 단순히 문자열을 넣은 것이 아닌 StringBuffer 객체를 생성하여 문자열을 붙인 것을 확인할 수 있다.

※append() 메소드는 문자열을 붙여주는 기능을 수행한다. 자세한 사항은 아래에서 자세히 다룰 예정이다.

 

내부에서 발생하는 일을 보면 세 가지의 문장을 붙이기 위해서 StringBuffer 객체 3개를 생성하는 것을 볼 수 있다.

이 객체들은 문자열을 합치는 과정이 완료되면 자동으로 소멸(Garbage Collection)한다.

즉, 새로운 버퍼를 생성하는데 메모리의 낭비가 발생하고 추가적인 작업이 발생하게 된다.

 

하지만 애초에 StringBuffer 를 사용한다면 이런 비용적인 문제를 해결할 수 있다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append("Hello");
		sb1.append(" world");
		sb1.append(" Welcome");
		System.out.println(sb1);
 

실행 결과를 보면 같은 결과가 나온 것을 확인할 수 있다.

StringBuffer 클래스는 부적으로 String 객체가 아닌 char[ ](문자형 배열) 을 사용하여 내용의 추가 또는 삭제와 같은 변환이 가능(가변성)하다.

지난 포스팅에서 String 의 메소드를 정리하며 나온 subString() 과 replace 메소드를 사용하는 방법을 정리했다.

불변성인 String을 두 메소드를 통해 내용을 변경할 수 있던 이유는 위에서 말한바와 같이 새로운 객체를 생성하여 변경할 수 있던 것이다. 하지만 StringBuffer 의 경우 문자열 내용을 변경해도 새로운 객체를 만들지 않아도 된다.

즉, 비용적으로 String의 문자열을 변경하는 것 보다 훨씬 저렴하게 내용의 변경이 가능하다는 것이다.

따라서 빈번하게 문자열의 변경이 필요한 작업이라면 String 보다는 StringBuffer 를 사용하는 편이 좋다.

 

2. StringBuffer 선언하기 & 버퍼 크기 설정하기

버퍼를 만드는 방법은 총 3가지가 있다.

StringBuffer도 클래스이기에 인스턴스를 생성하며 생성자를 통해서 값 또는 버퍼의 사이즈를 설정할 수 있다.

                //16문자를 담을 수 있는 공간 생성
		StringBuffer strb1 = new StringBuffer();
		//100문자를 담을 수 있는 공간 생성
		StringBuffer strb2 = new StringBuffer(100);
		//"abcd" 가 저장된 공간 생성
		StringBuffer strb3 = new StringBuffer("abcd");
 

기본으로 생성하면 16개의 문자를 담을 수 있지만 실제로 사용하면 초과해서도 사용할 수 있다.

하지만 기본 사이즈를 벗어나면 오버헤드(과부화)가 발생하여 내부적으로 버퍼를 새로 만드는 작업을 수행한다.

이는 추가적인 비용이 발생하여 비효율적이므로 최초 생성 시 넉넉하게 사이즈를 잡아주는 것이 좋다.

 

 

3. StringBuffer의 메소드

StringBuffer는 가변성이다. 즉, 내용 변경이 자유롭기 때문에 내용을 변경하는 작업을 수행하는 메소드가 많다.

 

1) 값을 문자열로 변환하여 저장 append()

위에서 잠깐 언급했지만 append() 메소드는 문자열에 새로운 내용을 추가할 수 있다. 또 한 가지 기능으로는

문자형으로 변환한다는 것이다.

아래의 코드에서 보면 12345 는 정수이지만 실행 결과에서는 문자열로 변경되어 내용이 합쳐진 것을 볼 수 있다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append("Hello");
		sb1.append(" world");
		sb1.append(" Welcome");
		sb1.append(12345);
		System.out.println(sb1);
 

2) 버퍼의 전체 크기 구하기 capacity()

capacity()를 사용하면 버퍼에 할당된 전체 크기를 구할 수 있다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append("Hello");
		sb1.append(" world");
		sb1.append(" Welcome");
		sb1.append(12345);
		System.out.println("버퍼크기 : " + sb1.capacity());
		
		System.out.println(sb1);
 

StringBuffer의 인스턴스를 생성한 부분을 보면 16개의 글자를 담는 기본 사이즈로 생성된 것을 볼 수 있다.

그 후 인스턴스 sb1에 문자열을 추가 후 확인해 보면 아래의 실행 결과를 볼 수 있다.

오버헤드가 발생한 버퍼의 크기는 다음의 공식에 따라 크기가 재설정된다.

NewCapacity = (oldCapacity * 2) + 2

따라서 글자의 수가 24개지만 버퍼는 초기의 16개 이므로 (16*2)+2 하여 34의 사이즈가 잡힌다.

※동일한 버퍼에서 오버헤드가 자주 발생하여 일정 크기를 넘기면 입력된 문자열 만큼의 사이즈가 나오는 듯 하다.

 

3) 버퍼에 들어간 문자의 갯수 구하기 length()

버퍼에 실제로 들어간 문자의 갯수를 구한다. 사용 방법이나 메소드의 기능은 String 과 동일하다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append("Hello");
		sb1.append(" world");
		sb1.append(" Welcome");
		sb1.append(12345);
		System.out.println("버퍼크기 : " + sb1.capacity());
		System.out.println("문자열의 길이 : " + sb1.length());
		System.out.println(sb1);
 

 

4) 지정된 위치의 문자 수정하기 setCharAt()

String 클래스와 동일하게 지정된 위치의 문자가 무엇인지 찾아 수정한다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append(12345);
		sb1.setCharAt(3, '사');
		System.out.println(sb1); 
 

번외로 charAt() 메소드도 있다. 이 메소드는 인자로 입력된 index 번호의 위치에 어떤 단어가 있는지 찾아준다.

                System.out.println(sb1.charAt(3));
 

 

5) 문자열 중간에 값 바꾸기 replace()

charAt()이 특정 자리의 문자를 변경하였다면 replace() 는 범위를 지정하여 변경이 가능하다.

                StringBuffer sb1 = new StringBuffer();
		sb1.append(12345);
		sb1.replace(2, 4, "사");
		System.out.println(sb1);
 

실행 결과를 보면 2~4 번째 까지의 글자가 "사" 로 변경된 것을 볼 수 있다.

변경되는 단어 또한 setCharAt()과 달리 문자열인 것을 볼 수 있다.

 

6) 지정된 범위만큼 문자열 삭제 delete()

특정 자리에 있는 문자열을 삭제하는 메소드이다. 삭제된 문자열의 공간은 문자열 뒷쪽의 다른 문자열이 자동으로 붙는다.

                StringBuffer sb1 = new StringBuffer();
		
		sb1.append(12345);
		System.out.println(sb1);
		
		StringBuffer tsb = sb1.delete(1,3);
		System.out.println(tsb);
 

7) 원하는 위치에 문자 추가하기 insert()

StringBuffer는 가변성이므로 문자의 추가 또한 적은 비용으로 가능하다.

                StringBuffer sb1 = new StringBuffer();
		
		sb1.append(12345);
		System.out.println(sb1);
		
		sb1.insert(3, ".");
		System.out.println(sb1);
 
 

8) 문자열의 순서를 역순으로 변경 reverse()

말 그대로 문자열의 순서를 역순으로 재정렬한다.

                StringBuffer sb1 = new StringBuffer();
		
		sb1.append(12345);
		System.out.println(sb1);
		
		sb1.reverse();
		System.out.println(sb1);
 

 

9) 원하는 범위의 문자열 추출 subString()

String 클래스와 마찬가지로 원하는 범위까지의 문자열을 추출할 수 있다.

                StringBuffer sb1 = new StringBuffer();
		
		sb1.append(12345);
		System.out.println(sb1);
		System.out.println(sb1.substring(1, 3));
 
메소드 원형
기능
반환 값
append(String str)
값을 문자열로 변환하여 저장
Stringbuffer
capacity()
용량. 전체 공간의 크기
int
length()
들어가 있는 문자의 개수.
int
charAt(int index)
지정된 위치의 문자 구하기.
char
setCharAt(int index, char ch)
index 위치에 문자 변경
void
delete(int start, int end)
지정된 범위 만큼 문자열 삭제
Stringbuffer
insert(int offset, String str)
추가할 위치에 값을 삽입
Stringbuffer
replace(int start, int end, String str)
시작 ~ 끝 까지 변경할 문자열로 문자 치환
Stringbuffer
reverse()
문자열의 순서를 역순으로 변경
Stringbuffer
substring(int start, int end)
전체 문자열에서 원하는 문자열을 추출
String

 

※추가

1.

문자열을 취급하는 클래스는 StringBuilder 라는 클래스도 존재한다.

문자열이 처리되는 속도는 StringBuilder > StringBuffer > String 순으로 좋다.

StringBuilder 는 StringBuffer와 비슷하지만 StringBuilder의 경우는 단일 쓰레드 환경에서만 사용 가능하다.

따라서 단일 쓰레드 환경에서 처리속도에 민감한 작업이 필요할 때 StringBuilder를 사용한다.

 

2.

StringBuffer 의 비용적인 장점은 자바 내에서 처리 뿐 아닌 DB의 쿼리문 등을 처리할 때 유용하다.