[Java] String 말고 StringBuffer, StringBuilder

devdo·2021년 8월 4일
0

Java

목록 보기
18/59
post-thumbnail

String의 불변특성

String은 개발을 하면서 가장 많이 사용하는 레퍼런스 불변객체이다.
즉, String 객체에 변수에 할당되면 참조를 업데이트하거나 내부 상태를 어떤 방법으로도 변경할 수 없다는 것이다.

이런 String에 비효율적인 상황들이 있다. 바로 값을 이어붙이는(+=) 작업을 할 때이다.

예시를 보자.

        //  String vs StringBuffer vs StringBuilder
        // String 
        String ab = "";
        ab += "test";
        System.out.println("1ab = " + ab);
		
        // StringBuffer
        StringBuffer sbf = new StringBuffer("");
        sbf.append(ab);
        System.out.println("2ab = " + ab);

		// StringBuilder
        StringBuilder sbr = new StringBuilder("");
        sbr.append(ab);
        System.out.println("3ab = " + ab);

        long start1 = System.currentTimeMillis();
        for(int i =0; i<100000; i++){
            ab += "hello";

        }
        long end1 = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        for(int i =0; i<100000; i++){
            sbf.append("hello");

        }
        long end2 = System.currentTimeMillis();

        long start3 = System.currentTimeMillis();
        for(int i =0; i<100000; i++){
            sbr.append("hello");

        }
        long end3 = System.currentTimeMillis();


        System.out.println("1ab: "+(end1-start1));  // 4849 => 4.849초
        System.out.println("2ab: "+(end2-start2));  // 11 => 0.011초
        System.out.println("3ab: "+(end3-start3));  // 6 => 0.006초

결과

String을 값이 더하는('+') concat 같은 연산은 String이 immutable하기 때문에 문자열 A에 문자열 B를 더할 때 A에 B를 바로 덧붙이는 것이 아니라 새로운 문자열 객체를 C를 만들고 거기에 A와 B를 더한 결과를 담는 것이다. 다시 말해, 추가적으로 String 객체가 생성되고, A와 B의 값을 모두 복사하는 과정이 이루어진다. 그래서 엄청 느려지는 것이다.(4.256sec)


StringBuffer나 StringBuilder의 가변 특성(그리고 synchroized)

이런 String의 불변(immutable) 특성 때문에, 값을 변경할 수 없다. 그래서 변하지 않는 문자열 객체에 계속 덧붙이는 작업을 한다.

가변(mutable)객체인 StringBuffer나 StringBuilder의 값들은 변하기 때문에 append()메서드를 통해 계속 값을 갱신할 수 있다. 내부적으로 문자열 편집을 위한 Buffer(버퍼)가 존재하기 때문이다.

하지만 이 둘에도 차이를 알아야 한다. 바로 동기화(synchroized)관점에서 말이다.

StringBuffer는 멀티 스레드일 때도 안정적으로 사용할 수 있다.
반면에, StringBuilder는 단일 스레드일 때만 안정적이다.

왜냐하면,

StringBuffer는 동기화처리를 하는 synchroized 블록으로 주요 데이터 처리를 해 스레드가 많은 멀티 스레드일 때도 안전할 수 있다.(Thread-safe).

반면, StringBuilder는 synchroized 처리 키워드가 없어 동기화처리가 안되니 스레드가 많으면 안전할 수 없다. 그래서 단일 스레드에서만 사용해야 된다.

하지만 주로 String을 쓰는 이유는 자바는 컴파일시 이미 StringBuilder로 변환시켜주기 때문이다.

(단, for문 같은 반복문에서는 변환이 안된다!)

=> 사실 이런 것때문에 자바8버전의 Stream API를 쓰는 이유이기도 하다!


결론)

짧은 문자열을 처리할 때는 String, 스레드에 안전한 프로그램이 필요할 때나, 개발 중인 시스템의 부분이 스레드에 안전한지 모를 경우는 StringBuffer, 스레드에 안전한지의 여부와 전혀 관계 없는 프로그램을 개발할 경우는 StringBuilder를 사용하면 된다.



참고

profile
배운 것을 기록합니다.

0개의 댓글