String, StringBuffer, StringBuilder는 Java에서 문자열을 다루는 클래스
StringBuffer / StringBuilder 클래스는 문자열을 추가하거나 수정하는 작업을 수행할 때 주로 사용됩니다.
String에서도 + 연산이나 concat() 메서드로 문자열을 이어 붙일 수 있지만, 이 방식은 매번 새로운 String 인스턴스를 생성하므로 메모리 낭비가 발생하고 성능도 저하되는 단점이 있습니다.
따라서, Java에서는 StringBuffer 클래스를 제공하여 문자열 연산을 전용으로 하는 클래스를 따로 제공합니다.
StringBuffer
StringBuffer 클래스는 내부에 문자열을 저장하기 위한 가변 버퍼 공간을 가지고 있어, 문자열을 바로 추가하거나 수정할 수 있습니다.
이는 연산 시 새로운 객체를 생성하는 것이 아니기 때문에 메모리 낭비가 줄고, 문자열 연산 속도도 더 빠릅니다.
StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
String s = sb.toString();
sout(s); // "abc"
기본적으로 StringBuffer의 가변 버퍼 공간은 16개의 문자를 저장할 수 있는 크기이며, 생성자를 통해 크기를 설정할 수 있습니다
( 문자열 연산중에 할당된 버퍼의 크기를 넘게 되면 자동으로 버퍼를 증가시킴 )
[ StringBuffer 내장 메서드 ]
String str = "abc";
StringBuffer sb = new StringBuffer(str);
System.out.println("처음 상태 : " + sb); // 처음상태 : abc
System.out.println("String 변환 : " + sb.toString()); // abc
System.out.println("문자열 추출 : " + sb.substring(0,2)); // ab
System.out.println("문자열 추가 : " + sb.insert(2,"추가")); // ab추가c
System.out.println("문자열 삭제 : " + sb.delete(1, 2)); // ac
System.out.println("문자열 연결 : " + sb.append("q")); // abcq
System.out.println("문자열의 길이 : " + sb.length()); // 3
System.out.println("용량의 크기 : " + sb.capacity()); // 용량의 크기 구하기 : 3
System.out.println("문자열 역순 변경 : " + sb.reverse()); // 문자열 뒤집기
StringBuilder
위 StringBuffer와 동일 .. ..
StringBuffer vs StringBuilder
두 클래스 모두 거의 동일한 가변 문자열 처리 기능을 제공하지만, 스레드 안전성에 대해 차이가 존재합니다.
StringBuffer는 모든 메서드가 synchronized로 동기화되어 있기 때문에, 여러 스레드가 동시에 같은 객체를 수정해도 안전합니다.
( 대신 동기화 비용 때문에 속도가 느림 )
synchronized 키워드 : 여러 개의 스레드가 한 개의 자원에 접근할려고 할 때, 현재 데이터를 사용하고 있는 스레드를 제외하고 나머지 스레드들이 데이터에 접근할 수 없도록 막는 것
StringBuilder는 synchronized 동기화를 하지 않기 때문에 여러 스레드가 동시에 같은 객체에 접근할 시 스레드 안전하지 않습니다.
( 동기화 하지 않기에 속도가 빠름 )
[ 일반적으로 StringBuilder를 사용하는 이유 ]
불필요한 동기화 비용을 피하고 더 빠르기 때문
⇒ 일반적으로 문자열을 조작하는 대부분의 상황은 단일 스레드 환경이기 때문에 StringBuilder를 사용
String vs ( StringBuffer, StringBuilder )
가장 큰 차이점은 불변인가 가변인가입니다.
String은 불변이므로 한 번 생성된 문자열 값을 수정할 수 없습니다.
반면 StringBuffer와 StringBuilder는 문자열을 다룬다는 점에서는 String과 동일하지만, 내부에 가변 버퍼 공간을 사용하기 때문에 문자열을 직접 수정할 수 있다는 차이점이 있습니다.
StringBuffer, StringBuilder 클래스는 내부 버퍼 공간에 문자열을 저장해두고 이 안에서 추가, 수정, 삭제 작업을 할 수 있습니다.
String 객체는 equals() 메서드를 사용하여 동등 비교하지만, StringBuffer, StringBuilder는 equals() 메서드를 오버라이딩 하지 않았기 때문에 toString() 메서드로 String으로 변환 후 equals() 메서드를 사용하여 동등 비교해야 합니다.
+연산자 , String.concat() 메서드, StringBuiller, StringBuffer 사용
일반적으로 성능은 StringBuiller나 StringBuffer를 사용하는 것이 성능이 제일 좋음
String.concat() 메서드를 사용하는 경우 새로운 배열을 생성하여, 원본 문자열의 배열을 재구성하는 과정을 거치기 때문이 느림
결론적으로, 문자열 수정 작업이 없으면 String을 사용하고 문자열 수정 작업을 많이 하면 StringBuilder나 StringBuffer 사용
String 객체끼리 + 연산을 수행하면 새로운 String 인스턴스를 계속 생성하므로 비효율적이라고 알려져 있지만, 문자열 리터럴 간의 + 연산은 내부적으로 StringBuilder로 변환되어 append가 수행된 뒤, 다시 toString()으로 String 객체를 생성합니다.
하지만, 문자열 결합이 많아질수록 변환 비용이 커지므로 메모리 사용 효율이 떨어지게 됩니다
String a = "";
for (int i = 0; i < 10000; i++) {
a = a + i;
}
/* 위는 아래와 같음 */
String a = "";
for (int i = 0; i < 10000; i++) {
a = new StringBuilder(b).append(i).toString();
}