Java의 String, StringBuffer, StringBuilder의 차이점 분석

여러분도 String과 String Buffer의 차이에 대해 잘 알고 있으리라 믿습니다. 하지만 아마도 많은 동지들이 이 두 종류의 작업 원리에 대해 잘 모르는 부분이 있을 것입니다. 오늘 저는 여기서 이 개념을 다시 복습해 드리겠습니다. 그리고 J2SE 5.0에서 가져온 새로운 문자 조작 클래스인 String Builder를 소개합니다.그렇다면 이 String Builder와 String Buffer, 그리고 우리가 가장 먼저 만난 String 클래스는 그런 차이가 있을까요?서로 다른 자리에서 우리는 어떤 것을 써야 합니까?나는 이 몇 가지 유형에 대한 자신의 견해를 말하고 모두가 의견을 제시하기를 바란다. 모든 사람이 틀린 부분이 있고 틀린 부분을 고치는 동시에 더욱 공부하기에 좋은 기회이다.간단하게 말하자면 String 유형과 String Buffer 유형의 주요 성능 차이는 사실 String이 변할 수 없는 대상이라는 데 있다(왜? 자바의 디자이너에게 물어보자. 왜 String은 원래 유형이 아니지?)따라서 매번 String 유형을 변경할 때마다 새로운 String 대상을 생성한 것과 같고 바늘을 새로운 String 대상을 가리키기 때문에 내용을 자주 바꾸는 문자열은 String을 사용하지 않는 것이 좋다. 왜냐하면 매번 대상을 생성할 때마다 시스템 성능에 영향을 미치기 때문이다. 특히 메모리에 인용되지 않는 대상이 많으면 JVM의 GC가 작업을 시작하는데 그 속도는 상당히 느릴 것이다.여기에 적당하지 않은 예를 들어 보겠습니다
 
String S1 = "abc";
For(int I = 0 ; I < 10000 ; I ++) // For
{
S1 + = "def";
S1 = "abc";
}
만약 그렇다면 이 for 순환이 끝난 후에 메모리에 있는 대상이 GC에 의해 정리되지 않았다면 메모리에 모두 2만여 개의 놀라운 숫자가 있을 것이다. 만약에 이것이 많은 사람들이 사용하는 시스템이라면 이런 숫자는 많지 않을 것이다. 그러므로 여러분이 사용할 때 반드시 조심해야 한다.StringBuffer 클래스를 사용하면 결과가 달라집니다. 매번 결과는 StringBuffer 대상 자체를 조작하는 것이지 새로운 대상을 생성하고 대상 인용을 바꾸는 것이 아닙니다.따라서 일반적인 상황에서 StringBuffer, 특히 문자열 대상이 자주 바뀌는 경우를 추천합니다.특정한 상황에서 String 대상의 문자열 결합은 JVM에 의해 StringBuffer 대상의 결합으로 해석되기 때문에 이런 때 String 대상의 속도는 StringBuffer 대상보다 느리지 않다. 특히 다음과 같은 문자열 대상 생성에서 String 효율은 StringBuffer보다 훨씬 빠르다
 
String S1 = "This is only a" + " simple" + " test";
StringBuffer Sb = new StringBuilder("This is only a").append(" simple").append(" test");
String S1 대상을 생성하는 속도가 너무 빠르다는 것을 놀라게 될 것이다. 이때 String Buffer는 속도적으로 전혀 우세하지 않다는 것을 알게 될 것이다.사실 이것은 JVM의 수작이다. JVM의 눈에는 이것이다
 
String S1 = "This is only a" + " simple" + "test"; : String S1 = "This is only a simple test"; 。 , String , , :
String S2 = "This is only a";
String S3 = " simple";
String S4 = " test";
String S1 = S2 +S3 + S4;
이때 JVM은 규칙적으로 원래의 방식대로 할 것이다. S1 대상의 생성 속도는 아까처럼 빠르지 않다. 이따가 우리는 테스트를 해서 검증할 수 있다.이로써 우리는 첫 번째 결론을 얻었다. 대부분의 상황에서 String Buffer > String과 String Builder는 그들과 비교하면 어떨까?먼저 간단하게 소개해 드리겠습니다. StringBuilder는 JDK5.0에 새로 추가된 클래스입니다. StringBuffer와 차이점은 아래의 소개(출처 JavaWorld): Java입니다.lang. StringBuffer 스레드가 안전한 가변 문자 시퀀스입니다.String과 같은 문자열 버퍼는 수정할 수 없습니다.문자열 버퍼를 여러 스레드에 안전하게 사용할 수 있습니다.필요할 때 이 방법들을 동기화할 수 있기 때문에 임의의 특정한 실례상의 모든 조작은 마치 직렬 순서로 발생하는 것 같다. 이 순서는 관련된 모든 라인에서 진행되는 방법과 호출 순서가 일치한다.모든 문자열 버퍼는 일정한 용량을 가지고 있다.문자열 버퍼에 포함된 문자 시퀀스의 길이가 이 용량을 초과하지 않는 한 새로운 내부 버퍼 그룹을 할당할 필요가 없습니다.내부 버퍼가 넘치면 이 용량은 자동으로 증가합니다.JDK 5.0부터 이 클래스에 단일 스레드에 사용되는 등가 클래스, 즉 StringBuilder를 추가합니다.이 클래스에 비해 StringBuilder 클래스를 우선적으로 사용해야 합니다. 모든 같은 작업을 지원하지만 동기화를 실행하지 않기 때문에 속도가 더 빠릅니다.그러나 StringBuilder의 인스턴스를 여러 스레드에 사용하는 것은 안전하지 않습니다.이러한 동기화가 필요하면 StringBuffer를 사용하는 것이 좋습니다.이렇게 말하면 모두들 그들 사이의 차이를 알 수 있을 것 같다. 그러면 다음은 일반적인 추론을 하나 더 하자. 대부분의 경우 StringBuilder > StringBuffer. 따라서 이 부등식의 전달 정리에 따라 대부분의 경우 StringBuilder > StringBuffer > String에 이런 추도 결과가 나왔으니 테스트 검증을 해보자. 테스트 코드는 다음과 같다
 
public class testssb {

/** Creates a new instance of testssb */
final static int ttime = 10000;//
public testssb() {
}

public void test(String s){
long begin = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s += "add";
}
long over = System.currentTimeMillis();
System.out.println(" "+s.getClass().getName()+" : " + (over - begin) + " " );
}

public void test(StringBuffer s){
long begin = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s.append("add");
}
long over = System.currentTimeMillis();
System.out.println(" "+s.getClass().getName()+" : " + (over - begin) + " " );
}

public void test(StringBuilder s){
long begin = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s.append("add");
}
long over = System.currentTimeMillis();
System.out.println(" "+s.getClass().getName()+" : " + (over - begin) + " " );
}

// String
public void test2(){
String s2 = "abadf";
long begin = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
String s = s2 + s2 + s2 ;
}
long over = System.currentTimeMillis();
System.out.println(" : " + (over - begin) + " " );
}

public void test3(){
long begin = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
String s = "abadf" + "abadf" + "abadf" ;
}
long over = System.currentTimeMillis();
System.out.println(" : "+ (over - begin) + " " );
}

public static void main(String[] args){
String s1 ="abc";
StringBuffer sb1 = new StringBuffer("abc");
StringBuilder sb2 = new StringBuilder("abc");

testssb t = new testssb();
t.test(s1);
t.test(sb1);
t.test(sb2);
t.test2();
t.test3();
}
}
상기 코드는 NetBeans 5.0 IDE/JDK1.6에서 컴파일되었고 순환 횟수 ttime가 10000회인 테스트 결과는 다음과 같다. 조작java.lang. String 유형에 사용된 시간은 4392ms입니다.lang. StringBuffer 유형에 사용된 시간은 0밀리초입니다.lang. StringBuilder 형식 사용 시간: 0밀리초 조작 문자열 대상 인용 추가 형식 사용 시간: 15밀리초 조작 문자열 추가 사용 시간: 0밀리초는 StringBuffer와 StringBuilder의 차이를 볼 수 없을 것 같습니다. ttime를 30000회에 추가해 보세요: 조작java.lang. String 유형의 사용 시간: 53444밀리초 조작java.lang. StringBuffer 유형에 사용된 시간은 15밀리초입니다.lang. StringBuilder 유형 사용 시간: 15ms 조작 문자열 대상 인용 추가 유형 사용 시간: 31ms 조작 문자열 추가 사용 시간: 0ms StringBuffer와 StringBuilder의 성능에 큰 차이가 없습니다. 100000까지 확대하면 String 유형에 대한 테스트가 추가되지 않습니다.String 유형에 대한 이렇게 큰 데이터 양의 테스트가 느리기 때문에...java를 조작합니다.lang. StringBuffer 유형의 사용 시간: 31밀리초 조작java.lang. StringBuilder 유형의 사용 시간은 16밀리초로 차이를 알 수 있지만 여러 차례의 테스트 결과 StringBuffer가 StringBuilder보다 빠르다는 것을 알 수 있습니다. 1000000까지 늘려 보십시오(당장은 아니겠죠?):자바를 조작합니다.lang. StringBuffer 유형의 사용 시간: 265ms 조작java.lang. StringBuilder 유형의 사용 시간: 219밀리초는 약간의 차이가 없고 결과는 안정적입니다. 더 크게 보십시오. ttime = 500000://Exception in thread "main"java.lang.Out OfMemory Error: Java heap space・・・・・・・・・・・・・・・・・・・・・・・・・ 허허, 됐어. 테스트 안 할래. 기본적으로 성능은 StringBuilder>StringBuffer>String이야.

좋은 웹페이지 즐겨찾기