시간적 여유가 있어. 정리를 다시 해볼까한다.
대부분의 개발자들은 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(가변)
- 동기화를 지원하지 않는다.
'Delvelopment > Java' 카테고리의 다른 글
[Java] System.identityHashCode()와 hashCode() 차이 (0) | 2022.01.21 |
---|---|
JUnit이란? JUnit5 (Assertion, 어노테이션) (0) | 2022.01.14 |
[JAVA] 산술, 비트, 관계, 논리, 3항, 화살표 연산자, java14 switch 문 (0) | 2022.01.06 |
[JAVA] 데이터 타입, 리터럴이란 , 변수의 Scope(범위) LifeTime(수명) (1) | 2022.01.03 |
[JAVA] JVM의 구성요소 및 동작원리 (0) | 2021.12.26 |
댓글