String vs StringBuilder vs StringBuffer
포스트
취소

String vs StringBuilder vs StringBuffer

String vs StringBuilder vs StringBuffer 를 비교 해보자.

Java 에서 문자열을 다루는 클래스는 3가지가 있다. 문자열의 추가 수정 삭제 등의 연산이 많지 않거나 멀티 스레드 환경을 고려 하지 않을 때는 어떤 클래스를 사용해도 크게 문제가 없지만, 연산이 빈번하고 멀티 쓰레드 환경에서는 각 클래스의 특징, 장단점을 알고 적절한 클래스를 사용하는것이 좋다.

  • String
  • StringBuilder
  • StringBuffer

String vs StringBuilder/StringBuffer

두가지로 나누어서 비교해 보았을때 가장 큰 특징은 불변함이다.

문자열의 추가, 수정, 삭제가 빈번할때 String 클래스를 사용하게 되면 힙 메모리에 많은 임시 가비지가 생성되어 어플리케이션에 악영향을 끼치게 된다.

1
2
    String str = new String("hello");
    str = str + "world"

-> “hello world” 라는 문자열이 힙에 새로 생성이 되고 “hello”는 gc 의 대상이 된다.

많은 연산이 발생할때 힙 메모리를 과하게 사용하게되는 문제가 발생하는데 이를 해결하기 위해서 java 는 StringBuilder/StringBuffer을 도입하였다.

StringBuilder/StringBuffer 는 각각 AbstractStringBuilder를 상속 받고있다.

StringBuffer

1
2
3
public final class StringBuffer
    extends AbstractStringBuilder
    implements Serializable, Comparable<StringBuffer>, CharSequence

StringBuilder

1
2
3
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence

AbstractStringBuilder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    byte[] value;

    /**
     * The id of the encoding used to encode the bytes in {@code value}.
     */
    byte coder;

    /**
     * The count is the number of characters used.
     */
    int count;
  ...

}

AbstractStringBuilder 를 살펴 보면 멤버 변수로 value, count를 가지고 있고

AbstractStringBuilder 내의 append를 살펴 보면 추가하고자 하는 문자열의 길이 만큼 배열의 길이를 늘려주고, 같은 공간을 사용함으로써 값은 변경되지만 같은 공간을 사용하는 가변성을 제공하고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
}

이런 특징을 갖는 AbstractStringBuilder를 상속 받고 있기때문에 StringBuffer StringBuilderString과는 다르게 가변성을 가진다.

StringBuffer vs StringBuilder

둘다 가변성을 가지는 클래스임을 확인 하였는데 그렇다면 StringBuffer와 StringBuilder는 어떤 차이점이 있을까?

클래스 내부 구현을 확인해보면 그 차이점을 쉽게 확인 할 수 있다. 이번에도 동일하게 append를 살펴보자.

StringBuffer

1
2
3
4
5
6
    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

StringBuilder

1
2
3
4
5
    @Override
    public StringBuilder append(char[] str) {
      super.append(str);
      return this;
    }

얼핏 보기에 비슷해 보이지만 두 클래스의 차이점은 synchronized 키워드에 있다. 두클래스의 가장 큰 차이점은 동기화 유무이고 StringBuffer는 동기화 키워드를 제공하여 멀티스레드에 안전하다는 점이 있고, StringBuilder는 멀티스레드 환경에서 동기화를 지원하지는 않지만, 단일 쓰레드에서 뛰어난 성능을 보인다.

결론

  • String : 문자열 연산이 적고 멀티쓰레드 환경일 경우
  • StringBuffer : 문자열 연산이 많고 멀티쓰레드 환경일 경우
  • StringBuilder : 문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우

대부분 잘 알고있는 3가지 클래스를 비교해 보았고 각 클래스의 차이점이나 특징을 잘 알고 사용하자.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.