자바에서 문자열을 연결하는 방법을 살펴보고 각각의 효율성을 비교해 봅니다.

문자열을 연결하는 방법
1. + 연산자 이용
2. String 클레스의 concat 메소드 사용
3. StringBuffer의 append 사용
4. StringBuilder의 append 사용

네가지 경우에 대해 테스트를 작성합니다.

public class ConcatTest {

    private String s1;
    private String s2;

    @Before
    public void setUp(){
        s1 = "Hibernate";
        s2 = "Spring";
    }

    @Test
    public void plusOperator() {
        Long start = Calendar.getInstance().getTimeInMillis();

        for(int i = 0 ; i < 5000 ; i++){
            s1 = s1 + s2;
        }

        Long end = Calendar.getInstance().getTimeInMillis();

        System.out.println("Operator : " + (end - start));
    }

    @Test
    public void concatMethod() {
        Long start = Calendar.getInstance().getTimeInMillis();

        for(int i = 0 ; i < 5000 ; i++){
            s1 = s1.concat(s2);
        }

        Long end = Calendar.getInstance().getTimeInMillis();

        System.out.println("ConcatMethod : " + (end - start));
    }

    @Test
    public void stringBuffer() {
        Long start = Calendar.getInstance().getTimeInMillis();

        StringBuffer buffer1 = new StringBuffer(s1);
        StringBuffer buffer2 = new StringBuffer(s2);

        for(int i = 0 ; i < 5000 ; i++){
            buffer1.append(buffer2);
        }

        String result = buffer1.toString();

        Long end = Calendar.getInstance().getTimeInMillis();
        System.out.println("StringBuffer : " + (end - start));
    }

    @Test
    public void stringBuilder() {
        Long start = Calendar.getInstance().getTimeInMillis();

        StringBuilder builder1 = new StringBuilder(s1);
        StringBuilder builder2 = new StringBuilder(s2);

        for(int i = 0 ; i < 5000 ; i++){
            builder1.append(builder2);
        }

        String result = builder1.toString();

        Long end = Calendar.getInstance().getTimeInMillis();
        System.out.println("StringBuilder : " + (end - start));
    }

}

결과는 다음과 같습니다.

Operator : 1078
ConcatMethod : 500
StringBuffer : 15
StringBuilder : 0

Operator : 1062
ConcatMethod : 438
StringBuffer : 0
StringBuilder : 15

Operator : 1532
ConcatMethod : 453
StringBuffer : 0
StringBuilder : 16

Operator : 1172
ConcatMethod : 453
StringBuffer : 0
StringBuilder : 16

Operator : 1281
ConcatMethod : 453
StringBuffer : 16
StringBuilder : 16

Operator : 1171
ConcatMethod : 500
StringBuffer : 0
StringBuilder : 0

Operator : 1187
ConcatMethod : 454
StringBuffer : 0
StringBuilder : 16

흠.. 이상하네요. 예전에 영회형이 간단하게 정리 했었던 글과 정반대의 결과가 나왔습니다.
테스트는 Java 6.0을 사용했습니다.

StringBuffer와 StringBuilder 가 String 클레스에 있는 concat 메소드나 연산자에 비해 엄청나게 빠른것을 확인할 수 있습니다.

원인은 String의 immutable한 특징 때문입니다. API를 보시면 concat 메소드에 다음과 같이 적혀 있습니다.

If the length of the argument string is 0, then this String object is returned. Otherwise, a new String object is created, representing a character sequence that is the concatenation of the character sequence represented by this String object and the character sequence represented by the argument string.

즉 매번 새로운 String 객체를 만들게 되기 때문에 추가적인 비용이 많이 발생하는 것 같습니다. 하지만 그렇다 하더라도.. + 연산자 사용하는 것 보단 훨씬 낳습니다.

s1 = s1 + s2; 라는 한 문장이 두 개의 연산(더하기 연산과 대입 연산)을 포함하고 있기 때문에 저런 결과가 나왔다고 생각됩니다. 그렇다고 s1 + s2; 이렇게 표현할 수도 없고(컴파일에러) 참 난감하네요. :)

결론은 String이 Immutable한 특징 때문에 StringBuilder나 StringBuffer를 사용하여 문자열을 이어 붙이는 것이 String 객체를 그냥 사용하는 것 보다 굉장히 효율적이라는 것입니다.