이미 String과 StringBuffer의 차이점은 다들 잘 알고 계시겠지만, 이 두 클래스의 작동 원리에 대해서는 아직 불명확한 분들이 많은 것으로 추정됩니다. 그런데 오늘은 이 개념을 모두를 위해 살펴보겠습니다. J2SE 5.0에 도입된 새로운 문자 연산 클래스 - StringBuilder. 그렇다면 이 StringBuilder와 StringBuffer 그리고 우리가 처음 만난 String 클래스의 차이점은 무엇입니까? 다양한 상황에서 어느 것을 사용해야 할까요? 나는 이러한 범주들에 대해 나의 견해를 공유하고 싶고, 또한 모두가 자신의 의견을 제시할 수 있기를 바랍니다.
간단히 말하면 String 유형과 StringBuffer 유형의 주요 성능 차이는 String이 불변 객체라는 것입니다. (왜? Java 설계자에게 String이 왜 기본 유형이 아닌지 물어보세요.) 따라서 매번 String 유형을 변경하는 것은 실제로 새 String 객체를 생성한 다음 새 String 객체에 대한 포인터를 가리키는 것과 같습니다. 따라서 객체가 바뀔 때마다 내용이 자주 변경되는 문자열에는 String을 사용하지 않는 것이 가장 좋습니다. 특히 메모리에 참조되지 않은 객체가 너무 많으면 JVM의 GC가 작동하기 시작하고 속도가 상당히 느려집니다. 다음은 그다지 적절하지 않은 예입니다.
String S1 = "abc"; For(int I = 0 ; I < 10000 ; I ++) // For 模拟程序的多次调用 { S1 + = "def"; S1 = "abc"; }
이 경우 for 루프가 완료된 후 메모리의 객체가 GC에 의해 지워지지 않으면 20,000개 이상의 객체가 있게 됩니다. , 놀라운 숫자이고, 이것이 많은 사람들이 사용하는 시스템이라면 이 숫자는 그다지 크지 않기 때문에 모두가 사용할 때 주의해야 합니다.
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 객체 생성 속도가 너무 빠르다는 사실에 놀랄 것입니다. 현재 StringBuffer는 전혀 이점이 없습니다. 속도. 사실 이는 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 객체의 생성 속도는 그렇지 않을 것이다. 이전처럼 빠르게 테스트를 해볼 수 있습니다.
이로부터 첫 번째 단계 결론을 얻습니다. 대부분의 경우 StringBuffer > String
그리고 StringBuilder는 이들과 어떻게 비교됩니까? 먼저 간략하게 소개하겠습니다. 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 类型使用的时间为: 4392 毫秒
操作 java.lang.StringBuffer 类型使用的时间为: 0 毫秒
操作 java.lang.StringBuilder 类型使用的时间为: 0 毫秒
操作字符串对象引用相加类型使用的时间为: 15 毫秒
操作字符串相加使用的时间为: 0 毫秒
好像还看不出 StringBuffer 和 StringBuilder 的区别,把 ttime 加到 30000 次看看:
操作 java.lang.String 类型使用的时间为: 53444 毫秒
操作 java.lang.StringBuffer 类型使用的时间为: 15 毫秒
操作 java.lang.StringBuilder 类型使用的时间为: 15 毫秒
操作字符串对象引用相加类型使用的时间为: 31 毫秒
操作字符串相加使用的时间为: 0 毫秒
StringBuffer 和 StringBuilder 的性能上还是没有太大的差异,再加大到 100000 看看,这里就不加入对 String 类型的测试了,因为对 String 类型这么大数据量的测试会很慢滴……
操作 java.lang.StringBuffer 类型使用的时间为: 31 毫秒
操作 java.lang.StringBuilder 类型使用的时间为: 16 毫秒
能看出差别了,但其中有多次的测试结果居然是 StringBuffer 比 StringBuilder 快,再加大一些到 1000000 看看(应该不会当机吧?):
操作 java.lang.StringBuffer 类型使用的时间为: 265 毫秒
操作 java.lang.StringBuilder 类型使用的时间为: 219 毫秒
有些少区别了,而且结果很稳定,再大点看看, ttime = 5000000 :
······ Exception in thread "main" java.lang.OutOfMemoryError: Java heap space ······
呵呵,算了,不去测试了,基本来说都是在性能上都是 StringBuilder > StringBuffer > String 的了。
更多Java之String、StringBuffer、StringBuilder的区别分析相关文章请关注PHP中文网!