문자열을 더하는 로직
문자열을 더하는 방법으로 무엇이 있을까?
- String 의 + 연산
- String.concat
- StringBuffer or StringBuilder 의 append 메서드
String 으로 문자열 더하기
String str = "String";
str += "plus";
- 문자열을 더하는 연산을 할 때는 String 으로 작성하면 무슨 문제가 발생할까
- String 으로 문자열 더하기 연산을 하면 더해진 문자열을 저장하는 String 객체를 하나 더 생성한다.
- 새로운 객체를 생성하여 메모리에 할당하는 연산과 이전과 같은 객체가 많이 쌓여 GC가 수행되는 연산까지 합쳐져 오버헤드를 발생하기 때문에 String 으로 더하기 연산은 오버헤드를 발생한다.
StringBuilder , StringBuffer 로 더하기 연산하기
StringBuilder sb = new StringBuilder("String");
sb.append("plus");
- StringBuilder 나 StringBuffer 는 가변 객체이다.
String + 연산은 실제론 StringBuilder 를 사용한다?
- 자바의 버전이 올라가면서 이러한 String 의 오버헤드를 줄이고자 컴파일 시점에 StringBuilder 로 최적화가 이루어진다.
String s = "Hello, " + "World!"; // 프로그램 코드
String s = "Hello, World!"; // 실제 컴파일 후 코드
- 위처럼 상수 문자열끼리 더할 땐 더해져 있는 문자열로 변경해준다.
// 프로그램 코드
String name = "Java";
String s = "Hello, " + name + "!";
// 실제 컴파일 후 코드
String s = new StringBuilder()
.append("Hello, ")
.append(name)
.append("!")
.toString();
- String 변수를 + 연산에 사용했다면 StringBuilder 로 변경해준다.
// 비효율적인 최적화
for (int i = 0; i < 3; i++) {
result = new StringBuilder()
.append(result)
.append(i)
.toString();
}
// 좋은 코드 가이드
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
sb.append(i);
}
String result = sb.toString();
- 하지만 위처럼 for 문 안에 StringBuilder 로 최적화가 이루어진다면 똑같이 StringBuilder 를 계속 생성하므로 오버헤드가 남아있다
- 따라서 for 문 전에 미리 객체를 생성하는 습관을 가지면 좋다
StringBuilder 가 String 보다 항상 성능이 좋을까?
- StringBuilder 나 StringBuffer 는 가변 객체이므로 크기를 넘으면 메모리를 더 크게 재할당하고 내용을 복사하는 오버헤드가 존재한다.
- 따라서 적은 양의 문자열 연산에서는 String 을 쓰나 StringBuilder 를 쓰나 차이가 크진 않다.
문자열 클래스 선택 기준
- 위에서 다뤘듯이 String 은 컴파일 시점에 StringBuilder 를 변환해주기도 하고 적은 양의 문자열을 연산할 때는 String 을 사용해도 큰 차이가 없다.
- 하지만 많은 문자열을 연산한다면 StringBuilder 를 사용하는 것을 권장한다.
- 추가로 thread-safe 해야한다면 StringBuffer 를 사용하자