문자열 a와 b를 가정합니다:
a += b
a = a.concat(b)
내부적으로는 같은 것일까요?
다음은 참조용으로 디컴파일된 컨캣입니다. '+' 연산자도 디컴파일하여 그 기능을 확인할 수 있으면 좋겠습니다.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
아니, 꼭 그런 것만은 아닙니다.
첫째, there& # 39 의 근소한 차이로 시맨틱스를. 만약 'a' 는 'null', 'a' a+ '하지만' 다음 '앨콩카트 던지는 누얼포인터렉세페시옹 (b) = b' 는 원래 값인 것처럼 'a' 치료 'null'. 또 '만' 방법을 사용할 수 있는 동안 concat () '+' 는 'String' 값을 자동으로 연산자입니다 변환하십시오 문자열으로 인수 (toString () '' 방법을 사용하여 객체에는). 따라서 'concat ()' 이 어떤 방식이 더 엄격한 받아들입니다.
'= a + b 클래스에 여바바 후드 아래에 쓰기 위해 간단한.'
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
이제 자바프 - 'c' 로 분해 (Sun JDK 에 포함). 다음과 같은 열거합니다 볼 수 있습니다.
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
따라서 '= a + b' 는 같습니다
a = new StringBuilder()
.append(a)
.append(b)
.toString();
Concat '방법' 이 더 빠를 것이다. 그러나 이 방법은 더욱 문장열 스트라이베이더 '승' 최소한 성능 면에서.
'소스 코드' 와 '문자열이어야 스트라이베이더' (및 그 패키지 pbs. (base class) 를 사용할 수 있는 세르히오치프 of the sun 에서 jdk. 보시다시피 틀렸다니까 구축에 챨 어레이입니다 (크기조정 필요한 경우) 를 만들 때 던진 후 거두어 최종 'String'. 실제 메모리 할당은 의외로 빨리 찾아온다.
니야즈가 맞지만, 특수 + 연산자는 Java 컴파일러에 의해 더 효율적인 것으로 변환될 수 있다는 점도 주목할 가치가 있습니다. Java에는 스레드에 안전하지 않고 변경 가능한 문자열을 나타내는 StringBuilder 클래스가 있습니다. 여러 문자열 연결을 수행할 때 Java 컴파일러는 다음과 같이 자동으로 변환합니다.
String a = b + c + d;
를
String a = new StringBuilder(b).append(c).append(d).toString();
로 변환하는 것이 큰 문자열의 경우 훨씬 더 효율적입니다. 제가 알기로는 컨캣 메서드를 사용할 때는 이런 일이 발생하지 않습니다.
그러나 빈 문자열을 기존 문자열에 연결할 때는 concat 메서드가 더 효율적입니다. 이 경우 JVM은 새 String 객체를 생성할 필요가 없으며 기존 객체를 반환하기만 하면 됩니다. 이를 확인하려면 <a href=http://java.sun.com/javase/6/docs/api/java/lang/String.html#concat(java.lang.String)<의 concat 설명서를 참조하세요.
따라서 효율성이 매우 중요하다면 비어 있을 가능성이 있는 문자열을 연결할 때는 concat 메서드를 사용하고 그렇지 않은 경우 +를 사용해야 합니다. 그러나 성능 차이는 무시할 수 있을 정도로 미미하므로 걱정할 필요가 없습니다.
내가 대신 다음 루프 뿐만 아니라 비슷한 실행했음 @marcio 테스트입니다.
String c = a;
for (long i = 0; i < 100000L; i++) {
c = c.concat(b); // make sure javac cannot skip the loop
// using c += b for the alternative
}
내가 던진 스트라이버일드리아펜드 () '에서', 딱 좋은 주옵니다 잘 알려져 있다. 각 시험은 각 10 배, 연파란색은 실행하십시오 100k 담당자 실행하십시오. 결과가 나타납니다.
다음은 가장 대답 (2008년). 그 시간에 따라 변하는 것을 보입니다. 내 주위에 있는 것을 알 수 있는 '+' 는 Java 최신값 벤치마크 브라운아저씨의 제마흐 2 배나 빠른 속도로 concat '8'.
내 벤치마트:
@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
public class StringConcatenation {
@org.openjdk.jmh.annotations.State(Scope.Thread)
public static class State2 {
public String a = "abc";
public String b = "xyz";
}
@org.openjdk.jmh.annotations.State(Scope.Thread)
public static class State3 {
public String a = "abc";
public String b = "xyz";
public String c = "123";
}
@org.openjdk.jmh.annotations.State(Scope.Thread)
public static class State4 {
public String a = "abc";
public String b = "xyz";
public String c = "123";
public String d = "!@#";
}
@Benchmark
public void plus_2(State2 state, Blackhole blackhole) {
blackhole.consume(state.a+state.b);
}
@Benchmark
public void plus_3(State3 state, Blackhole blackhole) {
blackhole.consume(state.a+state.b+state.c);
}
@Benchmark
public void plus_4(State4 state, Blackhole blackhole) {
blackhole.consume(state.a+state.b+state.c+state.d);
}
@Benchmark
public void stringbuilder_2(State2 state, Blackhole blackhole) {
blackhole.consume(new StringBuilder().append(state.a).append(state.b).toString());
}
@Benchmark
public void stringbuilder_3(State3 state, Blackhole blackhole) {
blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).toString());
}
@Benchmark
public void stringbuilder_4(State4 state, Blackhole blackhole) {
blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).append(state.d).toString());
}
@Benchmark
public void concat_2(State2 state, Blackhole blackhole) {
blackhole.consume(state.a.concat(state.b));
}
@Benchmark
public void concat_3(State3 state, Blackhole blackhole) {
blackhole.consume(state.a.concat(state.b.concat(state.c)));
}
@Benchmark
public void concat_4(State4 state, Blackhole blackhole) {
blackhole.consume(state.a.concat(state.b.concat(state.c.concat(state.d))));
}
}
결과:
Benchmark Mode Cnt Score Error Units
StringConcatenation.concat_2 thrpt 50 24908871.258 ± 1011269.986 ops/s
StringConcatenation.concat_3 thrpt 50 14228193.918 ± 466892.616 ops/s
StringConcatenation.concat_4 thrpt 50 9845069.776 ± 350532.591 ops/s
StringConcatenation.plus_2 thrpt 50 38999662.292 ± 8107397.316 ops/s
StringConcatenation.plus_3 thrpt 50 34985722.222 ± 5442660.250 ops/s
StringConcatenation.plus_4 thrpt 50 31910376.337 ± 2861001.162 ops/s
StringConcatenation.stringbuilder_2 thrpt 50 40472888.230 ± 9011210.632 ops/s
StringConcatenation.stringbuilder_3 thrpt 50 33902151.616 ± 5449026.680 ops/s
StringConcatenation.stringbuilder_4 thrpt 50 29220479.267 ± 3435315.681 ops/s
톰 올바른지 + 연산자 있는 것이 무엇인지 정확히 설명하는 않습니다. '임시' 을 (를) '및 마감, 부품, 첨부됩니다 e-lab 은 스트라이베이더 toString ()'.
그러나 지금까지 모든 답을 효과가 하스팟 런타임용으로 개발하십시오 최적화 외면당하고 있다. 특히 이러한 임시 작업은 보다 효율적인 기계어 실행 시 일반 패턴과 대체되었는지 평가받고 있다.
@marcio: # 39, ve you& 만든 마이크로 벤치마트. # 39 의 현대적 JVM& 이 올바르지 프로필링하려면 운행에서어떠한 코드.
그 이유는 런타임 최적화 문제는 이러한 많은 차이가 있다 하더라도 한 번 더 하스팟 객체 생성 등 코드 - - 완전히 다른 것입니다. 확실하게 알 수 있는 유일한 방법은,,) 는 < 프로필링 코드에 i> situ< /i>.
마지막으로, 이 모든 방법을 실제로 매우 빠르다. 이렇게 될 경우 아직 최적화합니다. 코드가 있을 경우 그 문자열을 연결합니다 많이 방법은 아마도 알고리즘을 선택할 수 있는 최대 속도 아무런 상관이 없고 대신 you& # 39, re 연산자를 사용하여!
몇 가지 간단한 테스트를 어때? 사용되는 코드는 아래와 같습니다.
long start = System.currentTimeMillis();
String a = "a";
String b = "b";
for (int i = 0; i < 10000000; i++) { //ten million times
String c = a.concat(b);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
여러 차례 테스트되었습니다. Concat () '이' 가 버전 엑서큐션 반단면 시간이 있는 것으로 나타났다.
그 때문에 항상 새로운 방법을 concat () '이 나를 놀라게 했다' 는 문자열 (String (결과) ',' new it 가 " ". # 39 의 it& 것은 널리 알려진:
String a = new String("a") // more than 20 times slower than String a = "a"
왜 wasn& # 39 에서 작성, 컴파일러, a + b" 구체화하십시오 최적화합니다 " 수 없다. 그 결과 알고 항상 동일한 코드를 문자열? 피할 수 있다는 점에서 새로운 구체화하십시오 계시노라
기본적으로 두 가지 중요한 차이점을 + '와' concat 메서드입니다.
문자열 s = 10 + " Hello";;
이 경우 출력입니다 10Hello 합니다.
문자열 s = " I";; 구체화하십시오 s1 (am" ";) = s.콩카트 이콩카트 이콩카트 (boy" ";), (good" ";) 시스템지우트리프린틀린 (s1).
위의 경우 두 문장열 제공하기 위해 필수.
문자열 s = " I";; 구체화하십시오 s1 (am" ";) = s.콩카트 이콩카트 이콩카트 (boy" ";), (good" ";) 시스템지우트리프린틀린 (s1).
이 경우 총 7 명) 에 작성된 객체에는 풀마다 다음과 같습니다.
난 키워봤지 좋은 보이 Iam 야마구드 리엄 굿보이
지금 난 것 같은 문장열 콩카티나티 통해 작동자 +
S = " +" am" +";;;;; I" 문자열이어야 good" boy" +";; 시스템지우트리프린틀린 (s).
위의 경우 총 5 만 작성된 객체에는 있다.
실제로 그런 유지보수합니다 스트라이버퍼 를 통해 하나님이 콩카티나티 + 동일한 작업을 수행할 수 있는 것처럼 문장열 연산자입니다 클래스용 inet6.0 -
스트라이버퍼 sb = new 스트라이버퍼 (I" ";). 스발라펜드 (am" ";). 스발라펜드 (good" ";). 스발라펜드 (boy" ";). 시스템지우트리프린틀린 (sb).
이런 식으로 불과 5 객체에는 생깁니다.
그래서 보세요들 그것은꿈의 기본 차이점 및 + concat 메서드입니다. 경험하십시오:)
생각해서라도 정의를 & # 39 +& 완성도, 내가 하고 싶은 것을 추가 # 39;; 연산자입니다 [JLS SE8 15.18.1] [1] 에서 볼 수 있다.
>. 만약 오직 하나의 피연산자를 표현식에서는 형식은 구체화하십시오 관심용 구체화하십시오 >. 변환 (& # 167. 5.1.11) 을 수행한 다른 피연산자 만들기 위해 >. 구체화하십시오 런타임에. >. >. 그 결과 연결 문자열을 string 객체에 대한 참조입니다 >. 즉 연결은 두 피연산자를 써줬지 문자 >. 이 문자는 오른쪽 왼쪽 피연산자 앞장서니까요 있다. >. 피연산자) 에 새로 만들어진 구체화하십시오. >. >. String 객체가 새로 만든 (& # 167, 12.5) 는 한 표현식에서는 >. 상수입니다 표현식에서는 (& # 167, 15.28).
그 다음 구축현 대한 JLS 밝혔습니다.
>. 변환 및 연결 실행하십시오 구현 선택할 수 있습니다. >. 한 번에 그리곤요 만들지 않도록 중간 취소 >. String 객체에. 연속된 문자열이어야 성능을 향상시키는 >. 연결, 자바 컴파일러는 클래스 또는 스트라이버퍼 사용할 수 있습니다. >. 이와 유사한 방법을 중간 구체화하십시오 개체 수를 줄일 수 있습니다. >. 평가를 통해 만들어진 충족되었으며 expression. >. >. 더 프리미티브 유형, 구축할 수 있는 빼냅니다 최적화합니다 수도 있습니다. >. 래퍼 (wrapper) 에서 직접 객체 생성 변환하여 프리미티브 >. 맞추기바인딩 string. 유형
그래서 & # 39 를 볼 때, 자바 컴파일러는 클래스 또는 이와 비슷한 방법을 사용할 수 있습니다, 다른 컴파일러에도 스트라이버퍼 reduce& # 39, 다른 바이트 코드 생산할 수 있다.
[1]: http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html # jls-15.18.1
그렇지 않다고 생각합니다.
a.concat(b)는 문자열로 구현되며 초기 자바 머신 이후 구현이 크게 변경되지 않았다고 생각합니다. 연산
+구현은 자바 버전과 컴파일러에 따라 다릅니다. 현재
+는 가능한 한 빠른 연산을 위해 [
StringBuffer][1]를 사용하여 구현됩니다. 향후에는 변경될 수도 있습니다. 이전 버전의 Java에서는 문자열에 대한
+` 연산이 중간 결과를 생성하기 때문에 훨씬 더 느렸습니다.
나는 +=
가 +
를 사용하여 구현되고 비슷하게 최적화되었다고 생각합니다.
S # 39 를 사용할 때 속도를 줄일 수 있지만, +, concat 사용할 때, 길이 캐시-코어 string& 속도는 더욱 안정적인, 그리고 최고의 옵션은 스트라이베이더 클래스를 사용하여 작업을 하기 위해서는 안정적인 속도용 디스크입니다. diskid iqn.
뭐 이유를 이해할 수 있다. 그러나 완전히 만들기 위한 최선의 방법을 사용하고 있고, 속도는 이보다 긴 문장열 스트라이베이더 덮어쓰기/추가 () () 와 용납될 수 없다.