문제

2가 주어졌습니다 toString() 아래 구현, 선호하는 구현 :

public String toString(){
    return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

또는

public String toString(){
    StringBuilder sb = new StringBuilder(100);
    return sb.append("{a:").append(a)
          .append(", b:").append(b)
          .append(", c:").append(c)
          .append("}")
          .toString();
}

?

더 중요한 것은, 우리가 3 개의 속성 만 있다는 점을 감안할 때, 그것은 차이를 만들지 않을 수 있지만, 어떤 시점에서 당신은 어떤 시점에서 전환 할 것인가? + 연결 StringBuilder?

도움이 되었습니까?

해결책

버전 1은 더 짧기 때문에 바람직합니다 컴파일러는 실제로 버전 2로 전환합니다. - 성능 차이가 없습니다.

더 중요한 것은 우리가 3 개의 속성 만 있다는 점에서 더 중요한 것은 차이를 만들지 않을 수 있지만, 어떤 시점에서 당신은 유도에서 빌더로 전환합니까?

루프에서 연결하는 시점에서 - 일반적으로 컴파일러가 대체 할 수없는 경우입니다. StringBuilder 그 자체로.

다른 팁

핵심은 한 곳에 단일 연결을 쓰거나 시간이 지남에 따라 축적되는지 여부입니다.

당신이 준 예에서는 StringBuilder를 명시 적으로 사용하는 데 아무런 의미가 없습니다. (첫 번째 케이스에 대한 컴파일 된 코드를보십시오.)

그러나 루프 내부에 문자열을 구축하는 경우 StringBuilder를 사용하십시오.

Hugearray가 수천 개의 문자열이 포함되어 있다고 가정하면 다음과 같은 코드가 있습니다.

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

매우 시간과 메모리 위로가 있습니다.

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();

나는 선호한다:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... 짧고 읽을 수 있기 때문에.

나는 할 것이다 ~ 아니다 반복 수가 매우 높은 루프 내부에서 사용하지 않는 한 속도로 최적화하십시오. 그리고 성능 차이를 측정했습니다.

많은 매개 변수를 출력해야한다면이 양식이 혼란 스러울 수 있다는 데 동의합니다 (주석 중 하나와 같이). 이 경우 더 읽기 쉬운 형식으로 전환 할 것입니다 (아마도 사용 TostringBuilder Apache -Commons의 - Matt B의 답변에서 가져와 성능을 다시 무시하십시오.

대부분의 경우 두 접근 방식 사이에 실제 차이는 보이지 않지만 이와 같은 최악의 시나리오를 쉽게 구성하기 쉽습니다.

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

출력은 다음과 같습니다.

slow elapsed 11741 ms
fast elapsed 7 ms

문제는 += 문자열에 추가되면 새 문자열을 재구성하므로 문자열의 길이 (둘 다)에 선형 비용이 듭니다.

그래서 - 당신의 질문에 :

두 번째 접근법은 더 빠르지 만 읽기 쉽고 유지하기가 어렵습니다. 내가 말했듯이, 특정한 경우에는 차이가 보이지 않을 것입니다.

또한 Append 또는 +를 사용하는지 여부에 대해 상사와 충돌했습니다. 그래서 나는 R & D.Alwounge를한다고 생각했지만 Michael Borgwardt 설명을 좋아하지만 누군가가 미래에 실제로 알아야 할 경우 설명을 보여주고 싶었습니다.

/**
 *
 * @author Perilbrain
 */
public class Appc {
    public Appc() {
        String x = "no name";
        x += "I have Added a name" + "We May need few more names" + Appc.this;
        x.concat(x);
        // x+=x.toString(); --It creates new StringBuilder object before concatenation so avoid if possible
        //System.out.println(x);
    }

    public void Sb() {
        StringBuilder sbb = new StringBuilder("no name");
        sbb.append("I have Added a name");
        sbb.append("We May need few more names");
        sbb.append(Appc.this);
        sbb.append(sbb.toString());
        // System.out.println(sbb.toString());
    }
}

위의 클래스의 분해는 다음과 같이 나옵니다

 .method public <init>()V //public Appc()
  .limit stack 2
  .limit locals 2
met001_begin:                                  ; DATA XREF: met001_slot000i
  .line 12
    aload_0 ; met001_slot000
    invokespecial java/lang/Object.<init>()V
  .line 13
    ldc "no name"
    astore_1 ; met001_slot001
  .line 14

met001_7:                                      ; DATA XREF: met001_slot001i
    new java/lang/StringBuilder //1st object of SB
    dup
    invokespecial java/lang/StringBuilder.<init>()V
    aload_1 ; met001_slot001
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    ldc "I have Added a nameWe May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    aload_0 ; met001_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    astore_1 ; met001_slot001
  .line 15
    aload_1 ; met001_slot001
    aload_1 ; met001_slot001
    invokevirtual java/lang/String.concat(Ljava/lang/String;)Ljava/lang/Strin\
g;
    pop
  .line 18
    return //no more SB created
met001_end:                                    ; DATA XREF: met001_slot000i ...

; ===========================================================================

;met001_slot000                                ; DATA XREF: <init>r ...
    .var 0 is this LAppc; from met001_begin to met001_end
;met001_slot001                                ; DATA XREF: <init>+6w ...
    .var 1 is x Ljava/lang/String; from met001_7 to met001_end
  .end method
;44-1=44
; ---------------------------------------------------------------------------


; Segment type: Pure code
  .method public Sb()V //public void Sb
  .limit stack 3
  .limit locals 2
met002_begin:                                  ; DATA XREF: met002_slot000i
  .line 21
    new java/lang/StringBuilder
    dup
    ldc "no name"
    invokespecial java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    astore_1 ; met002_slot001
  .line 22

met002_10:                                     ; DATA XREF: met002_slot001i
    aload_1 ; met002_slot001
    ldc "I have Added a name"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 23
    aload_1 ; met002_slot001
    ldc "We May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 24
    aload_1 ; met002_slot001
    aload_0 ; met002_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    pop
  .line 25
    aload_1 ; met002_slot001
    aload_1 ; met002_slot001
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 28
    return
met002_end:                                    ; DATA XREF: met002_slot000i ...


;met002_slot000                                ; DATA XREF: Sb+25r
    .var 0 is this LAppc; from met002_begin to met002_end
;met002_slot001                                ; DATA XREF: Sb+9w ...
    .var 1 is sbb Ljava/lang/StringBuilder; from met002_10 to met002_end
  .end method
;96-49=48
; ---------------------------------------------------------------------------

위의 두 코드에서 Michael이 옳다는 것을 알 수 있습니다. 각 경우 하나의 SB 객체 만 생성됩니다.

Java 1.5 이후 "+"및 StringBuilder.append ()와의 간단한 한 줄 연결은 정확히 동일한 바이트 코드를 생성합니다.

따라서 코드 가독성을 위해 "+"를 사용하십시오.

2 예외 :

  • 멀티 스레드 환경 : StringBuffer
  • 루프의 연결 : StringBuilder/StringBuffer

최신 버전의 Java (1.8) 사용 분해 (javap -c)은 컴파일러가 도입 한 최적화를 보여줍니다. + 또한 sb.append() 매우 유사한 코드를 생성합니다. 그러나 우리가 사용하는 경우 행동을 검사하는 것은 가치가 있습니다. + 루프에.

루프를 위해 +를 사용하여 문자열을 추가합니다

자바:

public String myCatPlus(String[] vals) {
    String result = "";
    for (String val : vals) {
        result = result + val;
    }
    return result;
}

바이트 코드 :(for 루프 발췌)

12: iload         5
14: iload         4
16: if_icmpge     51
19: aload_3
20: iload         5
22: aaload
23: astore        6
25: new           #3                  // class java/lang/StringBuilder
28: dup
29: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
32: aload_2
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: aload         6
38: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
44: astore_2
45: iinc          5, 1
48: goto          12

StringBuilder.Append를 사용하여 문자열 추가

자바:

public String myCatSb(String[] vals) {
    StringBuilder sb = new StringBuilder();
    for(String val : vals) {
        sb.append(val);
    }
    return sb.toString();
}

Bytecdoe :(for 루프 발췌)

17: iload         5
19: iload         4
21: if_icmpge     43
24: aload_3
25: iload         5
27: aaload
28: astore        6
30: aload_2
31: aload         6
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: pop
37: iinc          5, 1
40: goto          17
43: aload_2

약간의 것이 있습니다 눈부신 차이 그렇지만. 첫 번째 경우, 어디에 + 새로 사용되었습니다 StringBuilder 루프 반복을 위해 각각에 대해 생성되며 생성 된 결과는 toString() 전화 (29 ~ 41). 그래서 당신은 사용하는 동안 실제로 필요하지 않은 중간 줄을 생성하고 있습니다. + 운영자 for 고리.

Java 9에서는 버전 1이 변환되기 때문에 더 빠르야합니다. invokedynamic 전화. 자세한 내용은에서 찾을 수 있습니다 JEP-280:

아이디어는 전체 StringBuilder Append Dance를 Java.lang.invoke.stringconcatfactory로 간단한 호출 호출로 교체하는 것입니다.

Apache Commons-Lang은 다음과 같습니다 TostringBuilder 사용하기 쉬운 클래스. 그것은 append-logic을 다루는 것뿐만 아니라 당신의 tostring이 어떻게 보이기를 원하는지에 대한 서식을 모두 잘 수행합니다.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

모양이 보이는 출력을 반환합니다 com.blah.YourClass@abc1321f[a=whatever, b=foo].

또는 체인을 사용하여 더 응축 된 형태로 :

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

또는 반사를 사용하여 클래스의 모든 분야를 포함시키려는 경우 :

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

원하는 경우 토스트링 스타일을 사용자 정의 할 수도 있습니다.

성능의 이유로 사용 += (String 연결)은 낙담합니다. 그 이유는 다음과 같습니다. Java String 새로운 연결이 새로운 것을 수행 할 때마다 불변의 String 만들어졌습니다 (새 제품은 이미 오래된 지문과 다른 지문을 가지고 있습니다. 문자열 풀에서 ). 새로운 문자열을 만드는 것은 GC에 압력을 가하고 프로그램을 속도로 느리게합니다. 물체 생성이 비싸다.

아래 코드는 동시에 더 실용적이고 명확하게 만들어야합니다.

public static void main(String[] args) 
{
    // warming up
    for(int i = 0; i < 100; i++)
        RandomStringUtils.randomAlphanumeric(1024);
    final StringBuilder appender = new StringBuilder();
    for(int i = 0; i < 100; i++)
        appender.append(RandomStringUtils.randomAlphanumeric(i));

    // testing
    for(int i = 1; i <= 10000; i*=10)
        test(i);
}

public static void test(final int howMany) 
{
    List<String> samples = new ArrayList<>(howMany);
    for(int i = 0; i < howMany; i++)
        samples.add(RandomStringUtils.randomAlphabetic(128));

    final StringBuilder builder = new StringBuilder();
    long start = System.nanoTime();
    for(String sample: samples)
        builder.append(sample);
    builder.toString();
    long elapsed = System.nanoTime() - start;
    System.out.printf("builder - %d - elapsed: %dus\n", howMany, elapsed / 1000);

    String accumulator = "";
    start = System.nanoTime();
    for(String sample: samples)
        accumulator += sample;
    elapsed = System.nanoTime() - start;
    System.out.printf("concatenation - %d - elapsed: %dus\n", howMany, elapsed / (int) 1e3);

    start = System.nanoTime();
    String newOne = null;
    for(String sample: samples)
        newOne = new String(sample);
    elapsed = System.nanoTime() - start;
    System.out.printf("creation - %d - elapsed: %dus\n\n", howMany, elapsed / 1000);
}

실행 결과는 다음과 같습니다.

builder - 1 - elapsed: 132us
concatenation - 1 - elapsed: 4us
creation - 1 - elapsed: 5us

builder - 10 - elapsed: 9us
concatenation - 10 - elapsed: 26us
creation - 10 - elapsed: 5us

builder - 100 - elapsed: 77us
concatenation - 100 - elapsed: 1669us
creation - 100 - elapsed: 43us

builder - 1000 - elapsed: 511us
concatenation - 1000 - elapsed: 111504us
creation - 1000 - elapsed: 282us

builder - 10000 - elapsed: 3364us 
concatenation - 10000 - elapsed: 5709793us
creation - 10000 - elapsed: 972us

1 회의 결과 (JIT는 아직 일을하지 않았다)에 대한 결과를 고려하지 않으며, 10 번의 연결조차도 성과 페널티는 관련이있다. 수천 개의 연결에 대해 차이는 엄청납니다.

이 매우 빠른 실험에서 배운 교훈 (위의 코드로 쉽게 재현 할 수 있음) : 절대 사용하지 마십시오. += 문자열을 결합시키는 데, 몇 가지 연결이 필요한 매우 기본적인 경우에도 (말했듯이, 새로운 현을 만드는 것은 어쨌든 비싸고 GC에 압력을 가한다).

Tostring 방법을 가능한 한 읽을 수 있도록하십시오!

내 책에서 이것에 대한 유일한 예외는 당신이 할 수 있다면 입증하다 중요한 자원을 소비한다는 것은 나에게 :) (예, 이것은 프로파일 링을 의미합니다)

또한 Java 5 컴파일러는 이전 버전의 Java에 사용 된 필기 "StringBuffer"접근법보다 빠른 코드를 생성합니다. "+"를 사용하는 경우이 및 향후 향상은 무료로 제공됩니다.

StringBuilder를 사용하는 것이 현재 컴파일러에서 여전히 필요하고 있는지 여부에 대한 논쟁이있는 것 같습니다. 그래서 나는 2 센트의 경험을 줄 것이라고 생각했다.

나는있다 JDBC 10K 레코드의 결과 세트 (예, 한 번의 배치로 모든 것이 필요합니다.) + 연산자를 사용하면 내 컴퓨터에서 약 5 분이 걸립니다. Java 1.8. 사용 stringBuilder.append("") 동일한 쿼리의 경우 1 초 미만입니다.

그래서 차이는 엄청납니다. 루프 내부 StringBuilder 훨씬 빠릅니다.

아래 예를 참조하십시오.

//java8
static void main(String[] args) {
    case1();//str.concat
    case2();//+=
    case3();//StringBuilder
}

static void case1() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str = str.concat(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case2() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str+=UUID.randomUUID()+"---";
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case3() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    StringBuilder str = new StringBuilder("");
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str.append(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");

}

static void saveTime(List<Long> executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis()-startTime);
        if(executionTimes.size()%CALC_AVG_EVERY == 0) {
            out.println("average time for "+executionTimes.size()+" concatenations: "+
                    NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(()->0))+
                    " ms avg");
            executionTimes.clear();
        }
}

산출:

100000 연결의 평균 시간 : 0.096 MS AVG
100000 연합의 평균 시간 : 0.185 MS AVG
100000 연합의 평균 시간 : 0.327 MS AVG
100000 연합의 평균 시간 : 0.501 MS AVG
100000 연합의 평균 시간 : 0.656 MS AVG
길이의 문자열 : 1950000 in 17745ms
10000 개의 연결의 평균 시간 : 0.21 MS AVG
100000 연합의 평균 시간 : 0.652 MS AVG
10000 개의 연결의 평균 시간 : 1.129 MS AVG
100000 연합의 평균 시간 : 1.727 MS AVG
100000 연합의 평균 시간 : 2.302ms avg
길이의 문자열 : 1950000 in 60279ms
100000 연결의 평균 시간 : 0.002 MS AVG
100000 연결의 평균 시간 : 0.002 MS AVG
100000 연결의 평균 시간 : 0.002 MS AVG
100000 연결의 평균 시간 : 0.002 MS AVG
100000 연결의 평균 시간 : 0.002 MS AVG
길이의 문자열 : 1950000 in 100ms

문자열 길이가 증가함에 따라 연결 시간도 증가합니다.
그것이 어디에 있습니다 StringBuilder 확실히 필요합니다.
보시다시피, 연결 : UUID.randomUUID()+"---", 실제로 시간에 영향을 미치지 않습니다.

추신: 나는 생각하지 않는다 Java에서 StringBuilder를 사용할 때 이것의 복제품입니다.
이 질문은 이야기합니다 toString() 대부분의 시대는 거대한 끈의 연결을 수행하지 않습니다.

'+'를 사용한 성능 현명한 문자열 연결은 Java에서 문자열이 불변이기 때문에 완전히 새로운 문자열 사본을 만들어야하기 때문에 비용이 많이 듭니다. 연결이 매우 빈번한 경우에는 특별한 역할을합니다. 예를 들어 루프 내부. 다음은 제가 그런 일을하려고 할 때 내 아이디어가 제안하는 것입니다.

enter image description here

일반적인 규칙:

  • 단일 문자열 할당 내에서 문자열 연결을 사용하는 것은 정상입니다.
  • 큰 문자 데이터 블록을 구축하기 위해 루프를하는 경우 StringBuffer로 이동하십시오.
  • 문자열에서 += 사용하는 것은 항상 StringBuffer를 사용하는 것보다 덜 효율적이므로 경고 종을 울려 야합니다. 그러나 어떤 경우에는 획득 한 최적화가 가독성 문제와 비교하여 무시할 수 있으므로 상식을 사용하십시오.

여기에 있습니다 좋은 존 스키트 블로그 이 주제를 중심으로.

컬렉션을 반복하고 StringBuilder를 사용하려면 체크 아웃 할 수 있음을 지적 할 수 있습니까? Apache Commons Lang 그리고 StringUtils.join () (다른 맛)?

성능에 관계없이 StringBuilder를 만들고 루프를 위해 백만 번째 시각.

성능을 비교하기 위해 네 가지 다른 접근법을 비교했습니다. 나는 GC에 무슨 일이 일어나는지 정확히 모르지만, 나에게 중요한 것은 시간입니다. 컴파일러는 여기에서 중요한 요소입니다. Window8.1 플랫폼에서 JDK1.8.0_45를 사용했습니다.

concatWithPlusOperator = 8
concatWithBuilder = 130
concatWithConcat = 127
concatStringFormat = 3737
concatWithBuilder2 = 46


public class StringConcatenationBenchmark {

private static final int MAX_LOOP_COUNT = 1000000;

public static void main(String[] args) {

    int loopCount = 0;
    long t1 = System.currentTimeMillis();
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithPlusOperator();
        loopCount++;
    }
    long t2 = System.currentTimeMillis();
    System.out.println("concatWithPlusOperator = " + (t2 - t1));

    long t3 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder();
        loopCount++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("concatWithBuilder = " + (t4 - t3));

    long t5 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithConcat();
        loopCount++;
    }
    long t6 = System.currentTimeMillis();
    System.out.println("concatWithConcat = " + (t6 - t5));

    long t7 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatStringFormat();
        loopCount++;
    }
    long t8 = System.currentTimeMillis();
    System.out.println("concatStringFormat = " + (t8 - t7));

    long t9 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder2();
        loopCount++;
    }
    long t10 = System.currentTimeMillis();
    System.out.println("concatWithBuilder2 = " + (t10 - t9));
}

private static void concatStringFormat() {
    String s = String.format("%s %s %s %s ", "String", "String", "String", "String");
}

private static void concatWithConcat() {
    String s = "String".concat("String").concat("String").concat("String");
}

private static void concatWithBuilder() {
    StringBuilder builder=new StringBuilder("String");
    builder.append("String").append("String").append("String");
    String s = builder.toString();
}

private static void concatWithBuilder2() {
    String s = new StringBuilder("String").append("String").append("String").append("String").toString();
}

private static void concatWithPlusOperator() {
    String s = "String" + "String" + "String" + "String";
}
}

Java8에서 확인한 내용은 다음과 같습니다

  • 문자열 연결 사용
  • StringBuilder 사용

    long time1 = System.currentTimeMillis();
    usingStringConcatenation(100000);
    System.out.println("usingStringConcatenation " + (System.currentTimeMillis() - time1) + " ms");
    
    time1 = System.currentTimeMillis();
    usingStringBuilder(100000);
    System.out.println("usingStringBuilder " + (System.currentTimeMillis() - time1) + " ms");
    
    
    private static void usingStringBuilder(int n)
    {
        StringBuilder str = new StringBuilder();
        for(int i=0;i<n;i++)
            str.append("myBigString");    
    }
    
    private static void usingStringConcatenation(int n)
    {
        String str = "";
        for(int i=0;i<n;i++)
            str+="myBigString";
    }
    

많은 문자열에 문자열 연결을 사용하는 경우 정말 악몽입니다.

usingStringConcatenation 29321 ms
usingStringBuilder 2 ms

StringBuilder Append 접근 방식과 함께 가야한다고 생각합니다. 이유입니다

  1. 문자열은 문자열이 매번 새 문자열 객체를 생성하므로 (문자열은 불변의 객체이므로) 3 개의 객체를 생성합니다.

  2. String Builder를 사용하면 하나의 객체만이 만들어지고 [StringBuilder는 muttable]을 만들고 추가 문자열이 추가됩니다.

그런 간단한 문자열의 경우 사용하는 것을 선호합니다

"string".concat("string").concat("string");

순서대로 문자열을 구성하는 선호하는 방법은 StringBuilder, String#concat ()를 사용한 다음 과부하 + 연산자를 사용한다고 말합니다. StringBuilder는 + 연산자를 사용하는 것처럼 큰 문자열을 작동시킬 때 성능이 크게 증가합니다. .concat ()를 사용하는 데있어 한 가지 문제는 nullpointerexceptions를 던질 수 있다는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top