05AM

[JAVA] StringBuilder와 StringBuffer를 사용하는 이유와 차이점 본문

Programming Language/Java

[JAVA] StringBuilder와 StringBuffer를 사용하는 이유와 차이점

_05AM 2023. 10. 15. 17:43

☀️ 배경

코딩 테스트를 준비하며 java의 여러 메소드를 익히던 중 궁금한 점이 생겼다. `java.lang.String` 자체의 메소드들도 다양하게 존재하는데 `java.util.StringBuilder`나 `java.util.StringBuffer`를 사용하는 이유가 무엇일까? 아래에서 그 이유를 알아보자.

☀️ 불변 문자열 클래스 String

`String` 클래스는 불변한 문자열을 나타내며, 한 번 생성되면 내용을 변경할 수 없다. `String` 클래스는 내부적으로 문자열을 문자 배열(`char[]`)에 저장한다. 문자 배열은 변경할 수 있는 가변 객체가 아니기 때문에 문자열 내용을 수정하는 것이 불가능하다. 예를 들어 'Hello'라는 문자열을 생성하면 다음과 같이 문자 배열에 저장된다.

['H', 'e', 'l', 'l', 'o']

만약 이 문자열을 변경하려고 하면 새로운 문자열을 생성하게 된다. 예를 들어 'Hello'라는 문자열을 'World'로 변경하면 다음과 같이 두 개의 문자열이 생성된다.

['H', 'e', 'l', 'l', 'o']  ->  ['W', 'o', 'r', 'l', 'd']

☀️ String이 불변한 이유

1. 스레드 안정성

불변한 문자열은 여러 스레드에서 동시에 접근해도 안전하다는 장점이 있다. 한 번 생성한 문자열 객체는 변경되지 않으므로 여러 스레드에서 공유해도 문제가 되지 않는다.

 

2. 캐싱 가능

한번 생성된 문자열은 다시 생성되지 않는다. 따라서 동일한 문자열이 여러 번 사용될 때 메모리를 절약할 수 있으며, 문자열 리터럴 풀(literal pool)과 같은 최적화를 가능하게 한다.

 

3. 예측 가능한 동작

문자열이 변경되지 않으므로 다른 부분에서 문자열을 참조하는 동안 예상치 못한 변경 사항이 발생하지 않는다.

 

String 클래스는 불변하고 새로운 문자열을 생성하는 것이 주요 특징이다. 이러한 불변성은 다양한 장점을 제공하지만, 문자열을 변경할 때마다 새로운 문자열을 생성하는 비용이 발생한다. 이런 경우에 `StringBuilder`나 `StringBuffer`와 같은 가변 문자열 클래스를 사용하여 문자열을 동적으로 조작할 수 있다.

☀️ 가변 문자열 클래스 StringBuilder를 사용하는 경우

`StringBuilder` 클래스는 가변한 문자열을 나타내며, 문자열을 생성하거나 수정할 수 있다. 내부 버퍼를 사용하여 문자열을 동적으로 조작한다.

`StringBuilder`는 문자열 연산 시 내부 버퍼를 재사용하므로 메모리 사용량과 성능 측면에서 효율적이다. 단, 스레드 사용에서 안전하지 않으므로 멀티스레드 환경에서는 주의가 필요하다.

또한, `String`과는 다르게 메서드를 체이닝하여 연속적으로 문자열 조작이 가능하다. 예를 들어, `StringBuilder`로 문자열을 뒤집고 새로운 문자열을 추가하고 삭제할 수 있다. `String`에서는 메서드 체이닝이 불가능하며 각 메서드 호출마다 새로운 문자열 객체를 생성해야하기 때문에 문자열 조작이 자주 발생하는 경우 메모리 및 성능 오버헤드가 발생할 수 있다. 이 경우, `StringBuilder`를 사용하는 것이 성능상 이점이 있다.

☀️ 가변 문자열 클래스 StringBuffer를 사용하는 경우

`StringBuffer` 클래스는 `StringBuilder`와 동일하게 가변 문자열을 나타내는데, `StringBuffer`는 스레드 안전하다. 동기화된 메소드로 구현되어 멀티스레드 환경에서 안전하게 사용할 수 있지만, 단일 스레드 환경에서는 `StringBuilder`를 사용하는 것이 성능 면에서 더 효율적이다.

☀️ String 클래스의 문자열 조작 메소드

1. `concat(String str)` : 문자열을 다른 문자열과 연결하여 새로운 문자열을 반환

2. `replace(char oldChar, char newChar)` : 지정된 문자를 새로운 문자로 대체한 새로운 문자열을 반환

3. `toUpperCase(), toLowerCase()` : 대소문자 변환 메소드로, 문자열의 복사본을 반환

4. `substring(int beginIndex), substring(int beginIndex, int endIndex)` : 부분 문자열을 추출하여 새로운 문자열을 반환

5. `trim()` : 문자열의 앞뒤 공백을 제거한 복사본을 반환

☀️ StringBuilder 클래스의 문자열 조작 메소드

1. `append(String str)` : 문자열을 뒤에 추가하고 `StringBuilder`를 반환. 문자열 누적 변경 가능.

2. `insert(int offset, String str)` : 지정된 위치에 문자열을 삽입하고 `StringBuilder`를 반환

3. `replace(int start, int end, String str)` : 지정된 범위의 문자열을 다른 문자열로 대체하고 `StringBuilder`를 반환

4. `delete(int start, int end)` : 지정된 범위의 문자열을 삭제하고 `StringBuilder`를 반환

5. `reverse()` : 문자열을 뒤집음

 

참고

ChatGPT 답변

Comments