개발/Java

[Java] 자바 String, StringBuffer, StringBuilder 차이

zz132456zz 2021. 10. 24. 22:53
728x90

String

String 클래스는 변경 불가능한(immutable) 클래스이기 때문에 한번 생성된 String 인스턴스는 변경할 수 없다.

 

'+' 연산자를 이용해서 문자열을 결합할 때 인스턴스 내의 문자열이 바뀌는 것이 아니고 합쳐진 새로운 문자열이 담긴 String 인스턴스가 생성된다.

 

따라서 String 클래스에서의 문자열 결합은 연산할 때마다 새로운 문자열을 가진 인스턴스를 생성시키므로 메모리 공간과 메모리 할당 및 해제에 의해 성능이 낭비된다.

 

문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많아진다면 StringBuffer 클래스나 StringBuilder 클래스를 사용하는 게 유리할 것이다.

StringBuffer

String과 StringBuffer의 가장 큰 차이는 문자열의 내용을 변경할 수 있는 것이다.

 

다음은 StringBuffer의 생성과 변경을 간단하게 나타냈다.

// StringBuffer 생성
StringBuffer sb = new StringBuffer("abcd");  // sb : abcd

// StringBuffer 변경
sb.append("efgh");  // sb : abcdefgh
sb.append("ij").append("kl");  // sb : abcdefghijkl

 

다음은 StringBuffer의 비교에 대해서 알아볼 것이다.

// 같은 내용의 문자열을 가지는 두 StringBuffer 생성
StringBuffer sb1 = new StringBuffer("abcd");
StringBuffer sb2 = new StringBuffer("abcd");

System.out.println(sb1 == sb2);  // false
System.out.println(sb1.equals(sb2));  // false

// toString()을 호출하여 String 인스턴스를 생성
String s1 = sb1.toString();
String s2 = sb2.toString();

System.out.println(s1.equals(s2));  // true

위와 같이 StringBuffer는 equals 메서드가 오버라이딩되어 있지 않아서 equals는 물론 등가 비교 연산자 '==' 로도 문자열의 내용을 비교할 수 없다. 따라서 문자열의 내용을 비교하고 싶다면 toString()을 호출하여 String 인스턴스를 얻은 후 equals 메서드를 사용해서 비교해야 한다.

StringBuffer vs StringBuilder

StringBuffer와 StringBuilder는 한 가지 부분을 제외하고는 모든 부분의 기능이 완전히 동일하다.

 

StringBuffer는 멀티쓰레드에 안전하도록 동기화되어 있다. 때문에 멀티쓰레드로 작성된 프로그램이 아니라면 StringBuffer는 불필요하게 성능을 떨어뜨린다.

 

StringBuilder는 StringBuffer에서 쓰레드의 동기화만 빼면 완전히 동일한 기능을 한다. 따라서 멀티쓰레드 환경이 아니라면 StringBuffer로 구현한 모든 부분을 StringBuilder로 대체해주면 성능이 올라갈 것이다. 하지만 StringBuffer의 성능도 충분히 좋기 때문에 반드시 성능 향상이 필요하지 않다면 StringBuffer로 작성하는 게 마음이 편할 것 같다.

 

 


마지막으로 StringBuilder와 관련된 내용으로 알고리즘 문제 풀이에서 알아두면 유용한 팁을 작성해보겠다.

팁이라고 하기에는 별거가 아닐 수도 있지만.. 해당 내용을 생각해본 적 없는 사람에게는 좋은 정보가 될 것이다.

 

알고리즘 문제를 풀다 보면 명령어를 왕창 입력받고 특정 명령어가 들어올 때 문제에서 요구하는 내용을 출력해야 하는 문제를 풀어본 적이 있을 것이다. 나도 지금까지는 그냥 문제에서 요구하는 데로 그때그때 출력해서 문제를 풀었고 이상이 없었다. 근데 얼마 전에 푼 문제는 다른 모든 부분에서 시간을 최대한 단축했는데도 계속 시간 초과가 나길래 찾아보니 StringBuilder를 사용해서 해결이 가능했다.

 

중간중간에 출력할 일이 많이 생길 수 있는 경우는 그때그때 출력하지 않고 StringBuilder에 append 시켜놓고 마지막에 한 번만 출력하면 시간을 크게 단축할 수 있다. 물론 앞에서 설명한 내용과 같이 StringBuffer로 해도 같은 결과를 얻을 수 있을 것이다.

 

 

 

728x90