[정수리] String String Buffer String Builder의 차이점 분석

4394 단어 StringBuilder
이것은 매우 흔히 볼 수 있는 면접 문제이다. 적어도 나는 String/StringBuffer/StringBuilder의 차이점을 만난 적이 있다. String은 변할 수 없는 대상(final) 유형이다. 매번 String 대상에 대한 변경은 모두 새로운 String 대상을 생성하는 것이다. 원래의 대상은 변하지 않는다. 그에 비해 StringBuffer와 StringBuilder는 모두 변경할 수 있는 대상이고 효율이 String보다 크다. 이들의 차이점은 StringBuffer가 여러 라인에 적용되는 것이다.StringBuiler는 JDK5.0후부터는 StringBuffer보다 효율적인 단일 스레드를 위해 설계되었습니다.
 
String 테스트의 소스 코드:
	// 

	String str="abc";

	// tmp 

	String tmp=str;

	// , str , tmp str 

	str="abc"+str;

	// 

	System.out.println(str);//test

	System.out.println(tmp);//abc

	// , 

	long start=System.currentTimeMillis();

	for(int i=0;i<1000000;i++)

		str="a"+str;

	// , , , 

	System.out.println(System.currentTimeMillis()-start);

위의 코드는 명백하죠. 만약에 String이 가변 대상이라면str와 tmp의 결과는 같을 것입니다. 같은 공간을 가리키기 때문입니다. 그러나 마지막 결과가 다르기 때문입니다. String이 가리키는 공간은final 유형이기 때문에 변경할 수 없습니다.str="test"를 실행합니다. 실제로는 공간 저장test를 다시 신청했습니다. 그리고str는 "test"라는 공간을 가리켰습니다. tmp는 변하지 않았습니다. 마지막 시간 테스트에서매번str+"a"로 새로운 대상을 구성한 다음str를 이 새로운 대상으로 가리키기 때문에 str가 원래 가리키는 공간은 GC에서 회수하기 때문에 시간이 많이 걸릴 수 있습니다.
 
String 클래스가 구현한 부분의 원본 코드를 보십시오
public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence

{

    /**  , final, , */

    private final char value[];



    /** , */

    private final int offset;



    /** */

    private final int count;

너도 알다시피 문자열을 저장하는 데 사용되는 것은char형의 수조value이다. char의 앞에 있는final을 봐라. 알겠지:)
StringBuffer의 테스트 소스 코드:
	// StringBuffer , abc

	StringBuffer str=new StringBuffer("abc");

	//tmp StringBuffer 

	StringBuffer tmp=str;

	// , str , tmp str 

	str=str.append("abc");

	// 

	System.out.println(str);//abcabc

	System.out.println(tmp);//abcabc

	// , 

	long start=System.currentTimeMillis();

	for(int i=0;i<1000000;i++)

		str=str.append("a");

	// 63ms 

	System.out.println(System.currentTimeMillis()-start);

위의 코드도 명백한 것입니까? 조작은 시종일관 같은 대상이고 같은 메모리 공간이기 때문에 tmp와str의 값은 똑같습니다. 테스트 시간에 메모리의 방출과 회수를 피했기 때문에 (절대적으로 피하는 것이 아니라 메모리가 저장된 수량이 부족할 때 큰 공간을 재분배하고 전체적으로 말하면 감소된 메모리의 방출과 회수) 시간이 크게 줄어들었습니다.효율성이 향상되었습니다.
 public final class StringBuffer

    extends AbstractStringBuilder

    implements java.io.Serializable, CharSequence

{



    /** use serialVersionUID from JDK 1.0.2 for interoperability */

    static final long serialVersionUID = 3388685877147921107L;



    /**

     *  16B  

     */

  public StringBuffer() {

	super(16);

    }

여기에 아무것도 저장하지 않으면 StringBuffer에 16바이트의 기본 공간이 있음을 알 수 있습니다
StringBuffer의 상위 클래스를 보면 더 잘 알 수 있습니다.)
 
abstract class AbstractStringBuilder implements Appendable, CharSequence {

    /**

     * value , 16B , final :)

     */

    char value[];

이것들을 보면 String과 StringBuffer의 차이점을 알 수 있을 것이다. 그리고 하나는 StringBuffer가 라인이 안전하다는 것이다. 어디에 나타나는지 원본 코드를 보자.)
 
 
    public synchronized int length() {

	return count;

    }



    public synchronized int capacity() {

	return value.length;

    }





    public synchronized void ensureCapacity(int minimumCapacity) {

	if (minimumCapacity > value.length) {

	    expandCapacity(minimumCapacity);

	}

    }


위에서 보듯이 대부분의 방법은 하나의synchronized 키워드를 포함하고 있다. 이 키워드의 역할은 라인을 동기화하는 데 사용되기 때문에 다중 라인이 안전하다.
 
StringBuilder의 테스트 소스 코드:
	// StringBuilder , abc

	StringBuilder str=new StringBuilder("abc");

	//tmp StringBuffer 

	StringBuilder tmp=str;

	// , str , tmp str 

	str=str.append("abc");

	// 

	System.out.println(str);//abcabc

	System.out.println(tmp);//abcabc

	// , 

	long start=System.currentTimeMillis();

	for(int i=0;i<1000000;i++)

		str=str.append("a");

	// 36 

	System.out.println(System.currentTimeMillis()-start);

위의 코드도 유사하다. StringBuilder는 StringBuffer와 유사하지만 StringBuffer보다 효율적으로 바뀐다. 왜 그런지 원본 코드를 보면 알 수 있다.)
소스 코드에서StringBuffer와StringBuilder는 같은 부류를 계승하고 코드가 매우 비슷하다. 단지StringBuilder의 각 함수에synchonized 키워드가 적다. 이것은StringBuilder가 라인이 안전하지 않다는 것을 설명한다. 즉,synchronized 키워드가 있으면 코드가 실행할 때마다 이 대상을 잠그고 다른 대상이 이 방법을 호출하지 않도록 해야 한다. 단라인이든 다라인이든따라서 이것은 일정한 비용이 필요하기 때문에StringBuiler의 효율은StringBuffer:)보다 높다.

좋은 웹페이지 즐겨찾기