문자열 연결 (String Concatenation)
들어가며
회사에서 여유있을때 소스 리팩토링 좀 해보려고 한번씩 쭉 보고 있는데, 문자열 연결하는 부분이 거의 String.format으로 되어있었다.
특별히 이렇게 쓴 이유가 있을까??
이 방식이 다른 방법보다 속도나 성능면에서 우수한걸까??
라는 궁금증으로 시작해 찾아보게 되었다.
문자열 연결 방법 및 테스트
1. (+)연산자 (string + string)
2. StringBuilder
3. String.format
(concat, join 등등 여러 방법이 있지만 주로 사용하는 것들 세가지 정도만 테스트해봤다.)
@Test
public void 문자열_연결_테스트() {
final int COUNT = 1000000;
String header = "앞쪽에 붙일 문자열...";
String footer = "...뒤에 붙일 문자열";
String result;
long startTime;
startTime = System.currentTimeMillis();
for(int i = 0; i < COUNT; i++) {
result = header + "중간내용" + footer + "_" + i;
}
System.out.println("(+)연산자 : " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < COUNT; i++) {
stringBuilder.setLength(0);
stringBuilder.append(header)
.append("중간내용")
.append(footer)
.append("_")
.append(i);
result = stringBuilder.toString();
}
System.out.println("StringBuilder : " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for(int i = 0; i < COUNT; i++) {
result = String.format("%s%s%s%s%s", header, "중간내용", footer, "_", i);
}
System.out.println("String.format : " + (System.currentTimeMillis() - startTime) + "ms");
}
// (+)연산자 : 126ms
// StringBuilder : 56ms
// String.format : 1367ms
1,000,000건 기준으로 StringBuilder가 56ms로 가장 빨랐지만 연결할 문자열이 많아질 경우 가독성은 좋아보이지 않는다.
건수가 많지 않을 경우, 속도차이는 미미했지만 String.format이 좀 더 느린 것을 볼 수 있다.
(ex. 100건 기준
(+)연산자 : 0ms
StringBuilder : 0ms
String.format : 4ms)
결론
//String.format 내부의 parse 메서드
private static Pattern fsPattern = Pattern.compile(formatSpecifier);
/**
* Finds format specifiers in the format string.
*/
private FormatString[] parse(String s) {
ArrayList<FormatString> al = new ArrayList<>();
Matcher m = fsPattern.matcher(s);
for (int i = 0, len = s.length(); i < len; ) {
if (m.find(i)) {
...
String.format은 첫번째 인자로 정규식을 받기 때문에 Pattern / Matcher 클래스를 생성해준다.
이후 정규식을 검증하는 과정을 거치는데 단순 문자열 연결일 경우 정규식 검증을 위한 클래스 생성과 검증 비용은 불필요하다고 생각한다.
특정 포멧이 필요한게 아니라 단순 문자열 연결일 경우에는 +연산자, StringBuilder를 사용하는 것이 좋다고 생각하며, 건수가 많지 않을 것으로 생각되면 +연산자를 사용해 가독성까지 챙기는게 좋다고 생각한다.
Reference
https://kylewbanks.com/blog/java-string-concatenation-vs-stringbuilder-vs-string-format-performance
https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8