28. String Buffer와 String Builder

Isaiah IM·2023년 9월 18일
0

java basic

목록 보기
30/38
post-thumbnail

0. 문자열을 변경할 수 있는 클래스

기존의 String클래스는 문자열을 변경할 수 없다는 단점이 있었다. 그렇기에 문자열을 수정하는 작업을 할때는 변경된 문자열을 새로 메모리에 할당하는 다소 비효율적인 방식을 사용했었다.
그러나, 이번에 배울 StringBufferStringBuilder클래스는 문자열을 자유롭게 변경할 수 있는 클래스이다.


1. StringBuffer 클래스

1.1 StringBuffer클래스란?

StringBuffer 클래스는 문자열을 변경할 수 있는 클래스이다.

StringBuffer 클래스는 문자열을 변경할 수 있는 클래스로, 내부에 문자열 변경을 위한 버퍼(임시 저장장소)를 갖고 있어 문자열을 수정할 수 있으며, StringBuffer인스턴스를 생성할때 버퍼의 크기를 지정할 수 있다. 또한, 추가적으로 버퍼의 크기를 지정하지 않으면 자동으로 16개의 문자를 저장할 수 있는 버퍼가 생성이 되며, 버퍼가 부족할 경우 버퍼의 크기를 늘리는 작업이 진행되기 때문에 버퍼 크기를 충분하게 지정하는 것이 좋다.

1.2 StringBuffer 생성자

StringBuffer의 인스턴스 생성은 아래와 같다.

public class Main {
    public static void main(String[] args){
        StringBuffer sb1 = new StringBuffer("abcd");// string buffer 생성(abcd 저장됨, 버퍼크기 16)
        StringBuffer sb2 = new StringBuffer(100);// string buffer 생성(저장된 문자열x, 버퍼크기 100)
        
    }
}

위 코드에서 sb1에는 값abcd가 담겨있으며, 버퍼의 크기는 16글자까지 저장될 수 있다. 즉, 만약 문자열을 추가해서 sb1에 17글자를 입력하게 되면 자동적으로 버퍼의 크기를 늘리게 된다. 이때, 버퍼크기를 늘리는 것은 배열을 확장하는 작업과 동일하므로 효율이 좋지 않다.
sb2에는 값이 들어있지 않으나, 100글자를 저장할 수 있는 버퍼 크기를 갖는다.

1.3 StringBuffer 변경 및 비교

StrnigBuffer에서 값을 변경하는 원리는 다음과 같다.

StringBuffer는 기본적으로 버퍼라는 문자형 배열(char[])에 문자열을 저장하는 방식을 사용한다.
아래 그림과 같이 StringBuffer에 문자가 저장되 있다고 가정하자.

만약 위 배열에서 문자를 수정, 삭제, 추가 하는것은 배열이기에 인덱스에 접근해서 문자를 추가/수정/삭제를 하면 된다. 이렇듯 배열의 원리를 이용해 문자열을 수정하고, 추가하는 것이 Strngbuffer의 원리이다. 만약 StringBuffer에서 마지막에 문자열을 추가하고 싶은 경우에는 append()메소드를 사용하면 된다. 삭제의 경우 delete(int start, int end)메소드를 사용해 지울 수 있으며, 수정의 경우 replace(int start, int end, Strnig str)을 이용해 수정할 수 있다. 이때, start와 end는 삭제 및 수정할 배열의 인덱스를 의미한다.

public class Main {
    public static void main(String[] args){
       StringBuffer sb = new StringBuffer(100);

       sb.append("hello");
       sb.append(" world\n");

       sb.append("hello").append(" world");// 이렇게 해도 동일하게 동작한다

       String str= sb.toString();

       System.out.println(str);
    }
}

output

hello world
hello world

StringBuffer에서는 문자열을 배열로 비교를 하기 때문에 기존에 사용했던 == 연산 혹은 equals()메소드를 사용해 비교를 할 수 없다. 비교를 하기 위해서는 아래와 같이 toString()메소드를 사용해 문자열로 변환 후 equals()메소드를 사용해 비교를 해야 한다.

public class Main {
    public static void main(String[] args){
       StringBuffer sb1 = new StringBuffer(100);
       StringBuffer sb2 = new StringBuffer(100);

       sb1.append("hello world");
       sb2.append("hello world");

       String str1 = sb1.toString();
       String str2 = sb2.toString();

       System.out.println("sb1랑 sb2랑 같은가? "+ str1.equals(str2));

       sb1.append("java");
       str1 = sb1.toString();

       System.out.println("sb1랑 sb2랑 같은가? "+ str1.equals(str2));
    }
}

output

sb1랑 sb2랑 같은가? true
sb1랑 sb2랑 같은가? false

2. StringBuilder 클래스

2.1 StringBuilder클래스란?

Strnig builder클래스는 StringBuffer랑 동일하게 문자열을 추가/수정/삭제 할 수 있으며, 메소드 역시 동일하게 사용이 가능하나, 멀티스레드에서 동기화가 되지 않는다는 차이점이 있다.
멀티스레드에 대해서는 추후에 다루겠지만, StringBuffer의 경우 멀티스레드 환경에서도 수정된 값들이 정상적으로 적용이 되도록 동기화가 된다. 그러나, StringBuilder의 경우 멀티스레드 환경에서 동기화가 지원이 되지 않아 멀티스레드 환경에서 적합하지 않다. 물론, StringBuffer가 더 안전하지만, 싱글스레드 환경에서는 동기화가 필요가 없으므로 동기화 과정이 있는 StringBuffer보다는 StringBuilder가 더 성능이 좋다.


3. String vs StringBuffer vs StringBuilder

지금까지 StringBufferStringBuilder에 대해 알아보았다.
이 둘의 경우 둘 다 문자열을 수정할 수 있다는 장점이 있으나, 멀티스레드 환경에서의 동기화에 있어 차이가 존재한다. 그렇다면 문자열을 저장할때 어떤 클래스를 사용해야 효율적인지 알아보도록 하자.

문자열이 잘 바뀌지 않는 경우

프로그램 파일의 경로 등 문자열이 잘 바뀌지 않는 경우에는 String클래스를 활용을 하는 것이 가장 효율적이다. StringBufferStringBuilder는 결국 toString()이라는 메소드를 통해 문자열로 바꿔서 출력/비교를 해야 하기 때문에 문자열이 잘 바뀌지 않는 환경에서는 String클래스를 사용하는 것이 바람직하다.

문자열이 자주 바뀌는 경우

문자열이 자주 추가/삭제/수정이 되는 경우는 String클래스는 적합하지 않다. 이런 경우에는 문자열 수정이 쉬운 StringBuffer클래스 혹은 StringBuilder클래스를 사용하는 것이 바람직하다.

멀티스레드 환경

멀티스레드 환경에서는 동기화 문제로 인해 StringBuffer를 사용하는 것이 바람직하다. StringBuilder를 사용하면 동기화가 되지 않아 문자열 수정이 안되는 경우 역시 발생할 수 있기 때문이다.

싱글스레드 환경

우리가 지금까지 코딩해왔던 싱글스레드 환경에서는 동기화가 필요하지 않으므로 동기화 연산을 하지 않는 StringBuilder클래스를 사용하는 것이 더 효율적이다.

profile
나는 생각한다. 고로 나는 코딩한다.

0개의 댓글