01.JAVA/Java2008. 11. 5. 14:52
반응형
썬의 홈페이지에 실린 인터뷰 기사를 보다가...

Java의 오랜 미신 중에 하나...
"String 더하기 보다 StringBuffer append가 빠르다!?"

예를 들어... 아래의 코드는:

public static String concat1(String s1, String s2, String s3,
        String s4, String s5, String s6) {
    String result = "";
    result += s1;
    result += s2;
    result += s3;
    result += s4;
    result += s5;
    result += s6;
    return result;
}

이렇게 짜는게 좋다고... 가르치고 배운다. 나도 그렇게 배웠다:

public static String concat2(String s1, String s2,
        String s3, String s4, String s5, String s6) {
    StringBuffer result = new StringBuffer();
    result.append(s1);
    result.append(s2);
    result.append(s3);
    result.append(s4);
    result.append(s5);
    result.append(s6);
    return result.toString();
}

결론을 먼저 얘기하면, 새빨간 거짓말이다. 적어도 지금은 그렇다. 1.5 버전 이후의 썬의 자바 컴파일러를 사용한다면 확실히 그렇다.

StringBuffer를 사용해서 효과를 볼려면 이 정도는 해 줘야 한다:

public static String concat3(String s1, String s2, String s3,
        String s4, String s5, String s6) {
    return new StringBuffer(
        s1.length() + s2.length() + s3.length() + s4.length() +
        s5.length() + s6.length()).append(s1).append(s2).
        append(s3).append(s4).append(s5).append(s6).toString();
}

버퍼를 최초에 한번만 할당하면 append할때마다 버퍼 재할당을 하지 않으므로 확실히 빨라진다.
부작용은 코드가 극단적으로 읽기 힘들어 진다는 점. -.-;

옛날 얘기는 이쯤하고, 요즘 얘기를 해보자.

Java5에서 StringBuilder라는 새로운 클래스가 소개되었는데... 한마디로 요약하면 쓰레드에 안전하지 않은 StringBuffer다. 그런데 String은 immutable이라서 동기화 문제가 거의 없으므로, 예전에 StringBuffer쓰던 자리에 StringBuilder를 쓰면 된다.

똑같은 기능을 하는 함수를 가장 간단하게 구현하면 이렇다:

public static String concat4(String s1, String s2, String s3,
    String s4, String s5, String s6) {
    return s1 + s2 + s3 + s4 + s5 + s6;
}

1.5버전 이후의 썬의 자바 컴파일러는 concat4()처럼 짜면 StringBuilder append를 사용한 코드를 생성한다.

(위의 concat3()에서 사용한 방법까지 적용하면) 가장 효율적으로 구현하면 이렇게 된다:

public static String concat5(String s1, String s2, String s3,
        String s4, String s5, String s6) {
    return new StringBuilder(
        s1.length() + s2.length() + s3.length() + s4.length() +
        s5.length() + s6.length()).append(s1).append(s2).
        append(s3).append(s4).append(s5).append(s6).toString();
}

그러나, 여기서 고려해야할 점 두 가지:
1. 지금은 가장 효율적인 concat5()가 Java7이나 그 이후에도 가장 효율적이라는 보장이 없다.
2. concat4()가 concat5()보다 훨씬 읽기 좋다.

public static String concat6(String s1, String s2, String s3,
        String s4, String s5, String s6) {
    return new StringBuilder(BUFFER_SIZE).append(s1).append(s2).
        append(s3).append(s4).append(s5).append(s6).toString();
}


결론은:
1. 특별한 이유가 없다면 성능도 좋고 읽기도 좋은 concat4()가 최선의 선택이다.
2. 그러나 추가적인 계산없이, 버퍼 크기를 미리 알 수 있다면 concat6()도 나쁘지 않다.
3. 역시... 짜는 넘 맘이다.


출처 : http://iolothebard.tistory.com/291
Posted by 1010