자바에서 문자열을 저장하는데 사용되는 객체는 String, StringBuilder, StringBuffer 세 가지가 있다. 보통 문자열을 저장하는데 String 객체를 사용하지만 문자열을 빈번하게 수정할 필요가 있는 경우 String 객체보다는 StringBuilder 객체가 성능면에서 더 유리하다.


[표 1] 문자열 저장 객체간 비교

클래스명

특징

성능

메모리

String

불변하는 문자열 저장시 주로 사용


가장 낮다.

StringBuilder

수시로 가변하는  문자열 저장시 주로 사용

가장 높다.


StrungBuffer

다른 쓰레드 간 동기화가 필요한 경우 StringBuilder대신 사용




가변하는 문자열을 다루는데 있어서의 속도를 알아보기 위해서 다음과 같은 간단한 벤치마크 프로그램을 실행해 보았다. (JDK8 이용)



package tut_20;
import static java.lang.System.nanoTime;
public class Tut_20 {
 public static void main(String[] args) {
     long ls, le;
     long iter = 100000;

     ls = nanoTime();
     String str = "";
     for (int k = 0; k < iter; k++) {
         str += 'a';
     }
  System.out.println("String       :"+(nanoTime()-ls)/1e9+ "sec.");
       
       ls = nanoTime();
       StringBuilder strb = new StringBuilder();
       for (int k = 0; k < iter; k++) {
           strb.append('a');
       }
 System.out.println("StringBuilder:"+(nanoTime()-ls)/1e9+ "sec.");
       
       ls = nanoTime();
       StringBuffer strbf = new StringBuffer();
       for (int k = 0; k < iter; k++) {
           strbf.append('a');
       }
 System.out.println("StringBuffer :"+(nanoTime()-ls)/1e9+ "sec.");     
   }
}
실행 결과
String       :4.884195203sec.
StringBuilder:0.001943612sec.
StringBuffer :0.0015706sec.


결과는 보다시피 StringBuilder가 가장 빨랐고 StingBuilder 와 StringBuffer 는 차이가 별로 나지 않았다. (JDK5 이상에서는 String 객체도 수정이 일어날 때 내부적으로 StringBuffer로 변환되어 사용된다고 알고 있었는데 좀 의외다.)


 다음으로 문자열 내에서 검색하는 속도를 마찬가지로 간단한 프로그램을 실행하여 측정해 보았다. (JDK8 사용)


package tut_20;
import static java.lang.System.nanoTime;
import java.util.Random;

public class Tut_20 {
   public static void main(String[] args) {
       long ls, le;
       long iter = 100000000;

       String str = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";
       int len = str.length();
       char ch;
       Random rand = new Random();

       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = str.charAt(rand.nextInt(len));
       }
 System.out.println("String       :"+(nanoTime()-ls)/1e9+ "sec.");
       
       StringBuilder strb = new StringBuilder(str);
       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = strb.charAt(rand.nextInt(len));
       }
 System.out.println("StringBuilder:"+(nanoTime()-ls)/1e9+ "sec.");
       
       StringBuffer strbf = new StringBuffer(str);
       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = strbf.charAt(rand.nextInt(len));
       }
 System.out.println("StringBuffer :"+(nanoTime()-ls)/1e9+ "sec.");
   }
}
실행 시간
String       :1.258389526sec.
StringBuilder:1.414282314sec.
StringBuffer :3.205902914sec.


결과에서 나타났듯이 String 이 근소하게 StringBuilder 에 비해서 빨랐다.


 따라서 다음과 같이 정리해 볼 수 있겠다.


  1. 수정될 필요가 없는 문자열은 String 객체로 사용한다.

  2. 빈번에게 수정되는 문자열을 다룰 때는 StringBuilder 객체를 사용한다.

  3. 빈번에게 수정될 뿐만 아니라 서로 다른 쓰레드간 동기화를 시켜야 할 경우에는 StringBuffer를 사용한다.





Posted by 살레시오