티스토리 뷰

Java/Class

[java.lang] StringBuilder

MinChyang 2018. 1. 4. 18:07

StringBuilder Class



◎ Define

- StringBuilder Class는 String Class와 상반 되는 개념을 가지고 있다. String Class가 불변 객체이지만, StringBuilder Class는 가변 객체이다. 보통 자바 프로그램 내에서 문자열을 다룰(추가, 변경) 때 사용하며, 객체의 크기가 동적이다. 객체 생성 시 크기를 지정하지 않아도 기본적으로 16개의 문자를 저장할 수 있는 공간을 가진다.


- String은 가볍다, 하지만 불변 객체이다. StringBuilder는 String에 비해 무겁다, 하지만 가변 객체이다. (Explanation  참조)


- 자, 여기까지만 보면 StringBuffer와 StringBuilder는 너무도 흡사한 모습을 가지고 있다. String vs (StringBuffer or StringBuilder) 라고 볼 수 있다. 그렇다면 why? Buffer와 Builder로 나뉜 것일까? 이 둘의 차이점은 무엇일까? (Explanation  참조)



◎ StringBuilder Class Constructor


Constructor

Brief description

StringBuilder()

초기 문자열이 없고 16개의 문자를 저장할 수 있는 Buffer를 가진 객체 생성

StringBuilder(String str)

str의 문자열을 가지고 16개의 문자를 저장할 수 있는 Buffer를 가진 객체 생성

StringBuilder(int length)

초기 문자열이 없고 length개의 문자를 저장할 수 있는 Buffer를 가진 객체 생성



◎ StringBuilder Class Method


 Method

Brief description

void append(data)

전달된 데이터를 현재 문자열 끝에 추가한다.

int capacity()

현재 문자열의 총 용량 반환

char charAt(int index)

전달된 데이터 위치의 문자를 반환

delete(int start, int end)

전달된 start부터 end전 까지의 문자를 제거

delete(int index)

전달된 데이터 위치의 문자를 제거

int indexOf(String str)

해당 문자열에서 전달된 문자열과 일치하는 곳의 위치를 반환

int indexOf

(String str, int fromIndex)

해당 문자열에서 전달된 fromIndex부터 전달된 문자열과 일치하는 곳의 위치를 반환

void insert(int offset, data)

전달된 offset 위치에 전달된 data를 삽입

 int lastIndexOf(String str)

전달된 str의 마지막 index 위치를 반환

 int lastIndexOf

(String str, int fromIndex)

해당 문자열에서 전달된 fromIndex부터 전달된 str의 마지막 index 위치를 반환

 int length()

해당 문자열의 문자 개수를 반환

 StringBuilder replace

(int start, int end, String str)

전달된 start에서 end까지의 문자열을 전달된 str 문자열로 대체하여 반환

 StringBuilder reverse()

해당 문자열을 역순으로 된 문자열로 반환

 void setCharAt(int index, char ch)

해당 문자열에서 전달된 index 위치의 문자를 전달된 ch로 변환

void setLength(int newLength)

 해당 문자열의 Buffer 크기를 설정

String substring(int start)

해당 문자열에서 전달받은 start 위치부터 마지막까지의 문자열을 반환

 String substring(int start, int end)

해당 문자열에서 전달받은 start 위치부터 end 위치까지의 문자열을 반환

 String toString()

StringBuilder형인 문자열을 String형으로 변환



◎ Explanation


① StringBuilder Class와 String Class의 차이점에 대해서 알아보자.


참조)


1. 만약 문자열 추가나 변경 등의 작업이 많을 경우에는 StringBuilder를 사용하는 게 유리하고, 반대로 작업이 거의 없는 경우에 String을 사용하는 게 유리하다.


2. StringBuilder Class는 가변 객체이고, String Class는 불변 객체이다.


보통 초보 프로그래머의 입장에서는 해당 두 Class의 차이점에 대해 숙지를 하지 못 하고 있는 것이 대부분이다.


정확히 어떤 차이가 있는지 알아보자.


1. String을 불변 객체라고 말 하지만, 그렇다고 해서 String을 사용 했을 때 원하는 결과를 얻지 못 하는 것은 아니다.


밑에 예제를 보면서 이해 해보자.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class StringBuilderClass {
    public static void main(String[] args) {
        
        String str = "";
        str += "this";
        str += " ";
        str += "is String";
        System.out.println(str);
        // result : this is String
 
        StringBuilder sb = new StringBuilder();
        sb.append("this");
        sb.append(" ");
        sb.append("is String");
        System.out.println(sb.toString());
        // result : this is String
 
    }
}
cs



StringBuilder, String 모두 출력 값이 같은 걸 볼 수 있다. 즉, 위에서 말 했던 것처럼 결과를 얻지 못 하는 건 아니다.


그럼 무엇이 문제가 되는 걸까?


객체가 생성 되고 메모리가 사용 되는 과정이 다르다.


(Line 4~7) String 자료형에 + 연산이 있을 때마다 있던 객체는 GC(Garbage Collection) 되고 새로운 String 객체가 생성된다. (변경이 불가능한 불변 객체이기 때문이다.)


(Line 11) StringBuilder 객체를 생성 한 후


(Line 12~14) append() method를 이용해 문자열을 추가/변경 한다. 객체는 (Line 11)에서 단 한 번만 생성이 된다. (변경이 가능한 가변 객체이기 때문이다.)


크게 와닿지 않을 수도 있겠지만, 만약 프로그램상 수도 없이 많은 문자열 값이 추가/변경 된다고 가정 해보자.


이런 경우에 String을 사용한다면 그 수도 없는 추가/변경 작업을 할 때마다 있던 객체는 계속해서 GC 되고 새로운 객체를 생성 할 것이다.


GC가 많이 이루어진다는 것 자체가 그만큼 프로그램이 무거워지고 느려지게 하는 요인이 된다.


따라서 개발자가 프로그래밍을 할 때 어떤 도구를 사용해야 할 지 충분히 심사숙고 후 결정 하는 게


한층 더 Restful한 개발자가 되는 길이라고 할 수 있겠다.



② StringBuilder Class와 StringBuffer Class의 차이점에 대해서 알아보자.


참조)


1. 두 클래스의 차이점은 동기화 여부이다. StringBuffer Class 같은 경우에는 각 method 별로 Synchronized Keyword가 존재하여 Multi Thread 환경에서도 동기화를 지원하지만, StringBuilder의 경우 동기화를 보장하지 않는다.


즉, Multi Thread 환경이라면 값의 동기화 보장을 받기 위해 StringBuffer를,


Single Thread 환경이라면 StringBuilder를 사용하는 게 효율적이다.


물론 Multi Thread 환경이라면 동기화가 필요하기 때문에 Buffer를 사용한다고 쳐도


Single Thread 환경에서 Builder가 아닌 Buffer를 사용하면 안 돼느냐? 라는 의문이 들 수도 있다.


사용할 수 없는 건 아니다. 다만, Buffer의 동기화 관련 처리로 인해 Builder보다 성능 부분에서 떨어지게 된다.


모레사장에 1cm 가량의 구멍을 파기 위해 포크레인을 사용하는 것이라고 생각하고 이해하면 될 것이다.



여담)


String = 변경 될 요소가 없고 짧은 문자열을 가공 해야 할 경우 사용


StringBuilder = Single Thread 즉, Thread의 안전 여부가 전혀 관계 없는 프로그램을 개발할 때 사용


StringBuffer = Multi Thread 즉, Thread의 안전 여부가 필요 할 때나, 개발 중인 시스템의 부분이 Thread에 안전한 지 모를 경우 사용


성능 = StringBuilder > StringBuffer > String


Explanation ① 내용 중 String과 StringBuffer, StringBuilder GC(Garbage Collection)에 대한 이슈 부분을 조금 더 면밀히 보면,


사실 JDK 1.5 버전 이전에 많이 야기 되었던 이슈이다.


JDK 1.5 버전 이후부터는 String 객체를 사용 하더라도 문자열 연산이 들어간다면 컴파일 단계에서 자동으로 StringBuilder로 변환되도록 변경된 점이 있다.


그러므로 JDK 1.5 이상의 버전을 사용 할 땐 String 객체를 활용(추가/변경)해도 StringBuilder와 성능적인 부분에서 차이가 없어졌다고 보면 된다.


이렇게만 두고 본다면 Single Thread일 경우에는 String!


Multi Thread일 경우에는 StringBuffer! 를 사용하면 되겠다 라는 생각이 들 수도 있지만.. 여기서 또 하나의 이슈가 있다.


바로 반복 루프문을 사용 할 때 내부에서 문자열 연산이 들어갈 경우 GC 이슈가 발생을 한다는 점이다.


그러므로 이와 같은 사용법이 가장 효율적인 게 아닐까 라는 생각을 해 본다.


1. Single Thread  /  반복문 밖 = String


2. Single Thread  /  반복문 안 = StringBuilder


3. Multi Thread  /  모든 영역 = StringBuffer



※ 물론 여담에 관한 결론은 어디까지나 필자의 생각 일 뿐이다.









'Java > Class' 카테고리의 다른 글

[java.lang] Wrapper  (0) 2018.01.05
[java.lang] Math  (0) 2018.01.05
[java.lang] StringBuffer  (0) 2018.01.04
[java.lang] String  (0) 2018.01.03
[java.lang] Obejct  (0) 2018.01.03
댓글
Notice
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
Link
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함