Sky Archive

Java

[JAVA] 문자열을 합치는 여러가지 방법 (+, concat, StringBuilder, StringBuffer)

Anchovy ʕ-᷅ᴥ-᷄ʔ 2021. 12. 7. 01:32

문자열을 합치는 여러가지 방법 (+, concat, StringBuilder, StringBuffer)

 

안녕하세요.🐱‍🐉

오늘은 String Concatenation 연산 방법(문자열을 합치는 방법)들과 차이에 대해 알아보려고 해요. 

 

concat 메서드

String 클래스에서 제공하는 기본 메서드로, 문자열을 합칠 때 마다 새로운 인스턴스를 생성하기에 연산량이 많은 경우 는 당연히 권장하지 않아요. (합쳐지는, 합쳐진 문자열 모두 독립적으로 메모리 할당.)

또한 초기화되지 않으면 연산이 되지 않아요. (null과 연산시 NullPointerException 발생)

// 결과 : stir-fried anchovy
String str1 = "stir-fried";
String str2 = " anchovy";

sysout(str1.concat(str2));
// 결과 : java.lang.NullPointerException
String str1 = null;
String str2 = " anchovy";

sysout(str1.concat(str2));

 

StringBuilder

StringBuilder를 사용하는 방법은 아래와 같아요.

// 결과 : stir-fried anchovy
StringBuilder sb = new StringBuilder();
sb.append("stir-fried");
sb.append(" anchovy");

sysout(sb);

 

concat 메소드처럼 null과 문자열을 더하면 어떻게 될까요?

// 결과 : nullenchovy
String str1 = null;
String str2 = "enchovy";
StringBuilder sb = new StringBuilder();

sb.append(str1);
sb.append(str2);

sysout(sb);

 

왜 concat과 다른지는 StringBuilder가 상속받는 클래스 AbstractStringBuilder 내부를 보면 appendNull() 메소드를 통해 문자로 하나씩 붙여주는 걸 확인 할 수 있네요.

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
    
    ...
    
    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }
    
    ...
}
// AbstractStringBuilder append 부분

/**
 * Appends the specified string to this character sequence.
 * <p>
 * The characters of the {@code String} argument are appended, in
 * order, increasing the length of this sequence by the length of the
 * argument. If {@code str} is {@code null}, then the four
 * characters {@code "null"} are appended.
...
 */
public AbstractStringBuilder append(String str) {

 

StringBuffer

사용법은 StringBuilder와 같아요. 그렇다면 StringBuilder와의 차이는? StringBuffer는 thread-safe하다는 점에서 다른데 StringBuilder는 동기화를 보장하지 않아요. single thread 환경이라면 StringBuilder를, multi thread 환경에서는 StringBuffer를 사용합니다. StringBuilder는 동시성 제어 기능을 제외하여 상대적으로 동작속도가 빨라요.

multi thread 환경에서 하나의 문자열을 수정할 필요가 있다면 StringBuffer, 그렇지 않다면 StringBuilder 클래스를 사용하는 것이 좋을 것 같네요.

// 결과 : stir-fried anchovy
StringBuilder sbf = new StringBuffer();
sbf.append("stir-fried");
sbf.append(" anchovy");

sysout(sb);

 

※ '+' 연산자

Java 버전에 따라 다른데 1.5 이전에는 concat을 이용하는 방식과 같고 1.6 부터는 StringBuilder를 이용하는 방식과 같아요. (문자열을 먼저 StringBuilder로 변환시킨 뒤, Append로 문자열을 더하고 다시 toString함수로 문자열로 반환해주는 방식) 간단한 문자열 추가의 경우에는 읽기 편한 '+' 연산자가 더 좋을 수 있겠네요.

 

 

+ 그럼 String 대신 Stringbuilder나 Stringbuffer를 무조건 사용하여야 하는가?

String은 immutable 속성이 있기때문에 값이 바뀌지 않는다는 것을 알아야 해요. Stringbuilder나 Stringbuffer를 사용한다고 하더라도 toString을 사용해 String으로 변환하는 과정을 거쳐야 하고, 단순 조회 성능은 String이 앞서기 때문에 조회 작업이 많은경우 또는 변하지 않는 값을 사용하는 경우 String을 사용하는게 좋겠습니다.

또한 Stringbuilder나 Stringbuffer는 초기값이 16으로 초기화되기 때문에 연산이 필요하지 않은 경우는 필요하지 않아요.

 

 

 

 

 

 

ref. https://docs.oracle.com/javase/6/docs/api/java/lang/String.html