본문 바로가기
Delvelopment/Java

[Java] String, StringBuilder, StringBuffer 차이, 사용하기. 알고쓰자!

by 제제킴 2021. 6. 25.
반응형

시간적 여유가 있어. 정리를 다시 해볼까한다.

 

대부분의 개발자들은 String, StringBuffer, StringBuilder의 알고리즘적인 특징을 알아야 한다고 생각하며,

왜 쓰이는지에 대해서 써볼까한다.

 

연산속도는 String이 StringBuffer, StringBuilder 보다 느리고

메모리 관점으로 바라봐도 비효율적인 측면을 가지고있다.

 

즉, 단일 스레드 환경에서는 StringBuilder를 사용하고

멀티 스레드 환경에서는 StringBuffer가 적합하다. (Thread-safe)

 

하지만, 속도적인 측면에서는 비동기에 적합한 StringBuilder 가 적합하고 볼 수 있다.

 

String이 StringBuffer, StringBuilder 보다 연산속도가 느린이유는 String 클래스는 immutable 불변한 특징을 가지고 있기 때문이다.

 

StringBuffer, StringBuilder 는 동기, 비동기에 대한 차이를 가지고 있다.

StringBuffer는 synchronization를 지원해서 Thread-Safe한 특징을 가지고 있지만 StringBuilder 는 Thread-Safe 하지 않다.

세가지 클래스의 문자 연산속도의 성능 차이가 존재한다. 조금더 효율적으로 Java를 쓰기위해선 Java를 알아야한다.

 

 

반응형
String str = "ABC";
str = str + "123";

 

String 클래스를 위와 같이 "ABC" + "123" 으로 재정의 하게되면,

 String 클래스는 불변하기 때문에 String str = new String("ABC123"); 으로 객체를 재정의한다.

기존 str의 "abc"는 GC를 통해 삭제한다.

 

즉, String 클래스는 문자연산이 필요할때 Heap 메모리를 재정의 하는 프로세스 인 것이다.

이 장점으로 값이 변경되지 않기때문에 Thread-Safe한 장점을 가지게 된다.

만약 데이터의 변경이 빈번하지 않고 고정적이라면 String 클래스를 사용하는게 적합하다.

 

String str = "ABC";
System.out.printf("str | value: %-4s, address: %s\n", str, str.hashCode());
str = str + "123";
System.out.printf("str | value: %-4s, address: %s\n", str, str.hashCode());
str | value: ABC , address: 64578
str | value: ABC123, address: 1923891888

 

 

이와 반대로 StringBuffer, StringBuilder는 문자연산이 일어나게 되면 가변크기의 배열을 이용해서 필요한 경우에만 문자열을 복사한다.

 

public StringBuffer() {
    super(16);
}

@Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

최초 값의 크기는 16(기본값)으로 정의하고 append를 통해 문자를 추가한다.

 

StringBuffer sb = new StringBuffer();
sb.append("ABC");
System.out.printf("stringBuffer | value: %-4s, address: %s\n", sb, sb.hashCode());
sb.append("123");
System.out.printf("stringBuffer | value: %-4s, address: %s\n", sb, sb.hashCode());
stringBuffer | value: ABC , address: 1702146597
stringBuffer | value: ABC123, address: 1702146597

 

위와 결과처럼 StringBuffer는 append를 통해 필요한 크기 만큼 배열을 붙여넣는다.

 

이렇게 String, StringBuilder, StringBuffer 세가지의 특징을 살펴 보았고 아래와 같이 간단하게 정리할 수 있다.

 

  • String
    • immutable (불변)
    • 객체를 한 번 할당할시 메모리 공간에 변동이 없음. (할당시 Heap String Pool 영역에 생성되어 그 값을 계속 사용한다.)
    • 동기화를 신경쓰지 않아도 된다.
    • 엄청나게 많은 문자열을 선언 및 연산할 시 선능저하를 고려해야한다.
  • StringBuffer
    • mutable(가변)
    • 각 메서드별로 Synchronized Keyword가 존재한다.
    • 멀티스레드 환경에서도 동기화를 지원한다. (thread-safe)
  • StringBuilder
    • mutable(가변)
    • 동기화를 지원하지 않는다.

 

 

 

반응형

댓글