JAVA String 문자열 합치기 그리고 StringBuilder 사용

JAVA String 문자열 합치기 그리고 StringBuilder 사용

시작하기 앞서

최근에 알고리즘 공부를 하면서 문자열을 더하고 출력하는 문제를 풀었는데 메모리초과 오류가 났다.
최종 출력에는 정답과 일치했다.
그러나 문자열을 계산하는데 있어서 단순히 결과에만 집중하고 과정에는 집중하지 않았던것같다.
그래서 알아본 내용을 정리하겠다.

String

설명 요약

  • 불변 객체이다.
  • 기본타입이 아닌 참조타입이다.

리터럴 상수풀과 힙 메모리에 저장된 String객체

 String str = "Hello";
 str = str + " World";  // 새로운 str 객체 생성

위의 코드 첫줄에서 str객체를 만들었다. 이 때 "Hello"는 상수풀에 저장이 되고 str는 이를 가르킨다.
그리고 두번째 줄에서 생성한 객체와 " World"라는 문자열을 더해 다시 기존 객체에 저장했다.

그러나 실제로는 기존 객체에 연산을 하여 저장한것이 아니다.
str = new StringBuilder("Hello").append(" World").toString(); 라는 새로운 객체가 만들어진다.
이유는 두번째 줄 연산을 할 때 런타임에의해 str을 알 수 있기 때문이다.
이 때 " World"는 상수풀에 저장되지만 최종적인 "Hello World" 문자열은 힙메모리에 저장된다.

 String str = "Hello";
 str = "Hello" + " World";

만약 위와 같은 상황이라면

첫줄에서 Hello는 리터럴 상수풀에 저장이 되고
두번째 줄에서 Hello World가 리터럴 상수풀에 저장이 된다.
(아마 여기서 " World"는 상수풀에 저장되지 않을 것이다. .class파일을 보면 컴파일 타임에 이미 "Hello World"의 한 문자로 최적화 되어 합쳐져 있었다.)
그리고 str 객체는 기존 Hello에 대한 참조에서 Hello World로 참조를 변경한다.

이를 가장 빠르게 확인하는 방법은 아래 코드와 같다.

public class Main {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "Hello" + " World";

        System.out.println(str1 == "Hello");         // true
        System.out.println(str2 == "Hello World");   // true

        String str3 = "Hello";
        String str4 = str3 + " World";

        System.out.println(str4 == "Hello World"); // false
        System.out.println(str4.equals("Hello World")); // true
    }
}

문자열 합치기

만약 반복문을 통해 문자열을 합친다고 해보자.

for(int i = 0; i < 10; i++){
  str += i;
}

위와 같이 사용하면

str = new StringBuilder(str).append(i).toString();
위와 같은 str 객체를 10번이나 생성하게 된다.
그리고 10번이 아닌 N번이고 N의 크기가 매우 큰 경우 매번 객체를 생성할 것이다.

실제로 아래 실행시간 테스트를 해봤다.

Stirng 연산과 StringBuilder 연산의 실행시간 차이

문자열 합치기 실행 코드
문자열 합치기 실행 소요 시간

확실히 반복횟수가 커지니 차이가 많이 난다.

추가 내용

String a = "a" + "b" + "c" + "d" + "d" + "d" + "d" + "d" + "d" + "d" + "d" + "d" + "d" + "d" + "d" ··· 와 같이 사용하면
이는 컴파일타임에

String a = "abcddd···"와 같이 최적화 된다.

따라서 순수 리터럴 문자열과의 연산은 컴파일 타임에 최적화 되니 성능상에 문제가 되지 않는다는 걸 알 수 있다.

아무리 컴퓨터 성능이 좋아졌다 하지만 내 데스크탑에서도 실제로 많은 실행시간 차이가 발생하는걸 직접 보고 이런 부분들을 놓치지 않아야겠다는 생각이 들었다.