JDK 8 의 문자열 맞 춤 법 에 대한 자세 한 설명
자바 개발 자 들 사이 에서 문자열 의 조합 이 자원 을 차지 하 는 것 은 종종 화제 가 된다.
왜 높 은 자원 을 점용 하 는 지 깊이 토론 합 시다.
자바 에서 문자열 대상 은 가 변 적 이지 않 습 니 다.만 들 면 더 이상 바 꿀 수 없다 는 뜻 입 니 다.그래서 우리 가 문자열 을 맞 출 때 새 문자열 을 만 들 었 습 니 다.오래된 쓰레기 수 거 기 는 표 시 됩 니 다.
만약 우리 가 수백 만 개의 문자열 을 처리 한 후에,우 리 는 수백 만 개의 추가 문자열 을 쓰레기 회수 기 에 의 해 처리 할 것 이다.
대부분의 튜 토리 얼 에 서 는+번호 로 문자열 을 맞 추 면 여러 개의 String 을 생 성하 여 성능 이 떨 어 지 는 것 을 볼 수 있 습 니 다.StringBuffer/stringBuilder 를 사용 하 는 것 을 권장 합 니 다.
근 데 진짜 그런 거 예요?
본 고 는 JDK 8 에서 다음 과 같은 실험 을 했다.
public static void main(String[] args) {
String result = "";
result += "some more data";
System.out.println(result);
}
javap-c 를 통 해 역 컴 파일 할 수 있 습 니 다:
Code:
0: aload_0 // Push 'this' on to the stack
1: invokespecial #1 // Invoke Object class constructor
// pop 'this' ref from the stack
4: return // Return from constructor
public static void main(java.lang.String[]);
Code:
0: ldc #2 // Load constant #2 on to the stack
2: astore_1 // Create local var from stack (pop #2)
3: new #3 // Push new StringBuilder ref on stack
6: dup // Duplicate value on top of the stack
7: invokespecial #4 // Invoke StringBuilder constructor
// pop object reference
10: aload_1 // Push local variable containing #2
11: invokevirtual #5 // Invoke method StringBuilder.append()
// pop obj reference + parameter
// push result (StringBuilder ref)
14: ldc #6 // Push "some more data" on the stack
16: invokevirtual #5 // Invoke StringBuilder.append
// pop twice, push result
19: invokevirtual #7 // Invoke StringBuilder.toString:();
22: astore_1 // Create local var from stack (pop #6)
23: getstatic #8 // Push value System.out:PrintStream
26: aload_1 // Push local variable containing #6
27: invokevirtual #9 // Invoke method PrintStream.println()
// pop twice (object ref + parameter)
30: return // Return void from method
자바 컴 파일 러 가 생 성 된 바이트 코드 를 최적화 시 켜 StringBuilder 를 자동 으로 만 들 고 append 작업 을 하 는 것 을 볼 수 있 습 니 다.최종 문자열 을 구축 하 는 하위 문자열 은 컴 파일 할 때 이미 알 고 있 기 때문에 이러한 상황 에서 자바 컴 파일 러 는 위 와 같은 최 적 화 를 할 수 있 습 니 다.이러한 최 적 화 는 a static string concatenation optimization 이 라 고 하 는데 JDK 5 때 부터 사용 되 었 습 니 다.
그러면 JDK 5 이후 에 우 리 는 더 이상 StringBuilder 를 수 동 으로 생 성하 지 않 고+번 호 를 통 해 같은 성능 을 얻 을 수 있다 는 것 을 설명 할 수 있 습 니까?
동적 연결 문자열 을 시도 해 보 겠 습 니 다:
동적 연결 문자열 은 실행 할 때 만 최종 문자열 을 알 수 있 는 하위 문자열 을 말 합 니 다.예 를 들 어 순환 에 문자열 을 추가 합 니 다:
public static void main(String[] args) {
String result = "";
for (int i = 0; i < 10; i++) {
result += "some more data";
}
System.out.println(result);
}
같은 역 컴 파일:
Code:
0: aload_0 // Push 'this' on to the stack
1: invokespecial #1 // Invoke Object class constructor
// pop 'this' ref from the stack
4: return // Return from constructor
public static void main(java.lang.String[]);
Code:
0: ldc #2 // Load constant #2 on to the stack
2: astore_1 // Create local var from stack, pop #2
3: iconst_0 // Push value 0 onto the stack
4: istore_2 // Pop value and store it in local var
5: iload_2 // Push local var 2 on to the stack
6: i2d // Convert int to double on
// top of stack (pop + push)
7: ldc2_w #3 // Push constant 10e6 on to the stack
10: dcmpg // Compare two doubles on top of stack
// pop twice, push result: -1, 0 or 1
11: ifge 40 // if value on top of stack is greater
// than or equal to 0 (pop once)
// branch to instruction at code 40
14: new #5 // Push new StringBuilder ref on stack
17: dup // Duplicate value on top of the stack
18: invokespecial #6 // Invoke StringBuilder constructor
// pop object reference
21: aload_1 // Push local var 1 (empty String)
// on to the stack
22: invokevirtual #7 // Invoke StringBuilder.append
// pop obj ref + param, push result
25: ldc #8 // Push "some more data" on the stack
27: invokevirtual #7 // Invoke StringBuilder.append
// pop obj ref + param, push result
30: invokevirtual #9 // Invoke StringBuilder.toString
// pop object reference
33: astore_1 // Create local var from stack (pop)
34: iinc 2, 1 // Increment local variable 2 by 1
37: goto 5 // Move to instruction at code 5
40: getstatic #10 // Push value System.out:PrintStream
43: aload_1 // Push local var 1 (result String)
44: invokevirtual #11 // Invoke method PrintStream.println()
// pop twice (object ref + parameter)
47: return // Return void from method
14 시 에 new 가 StringBuilder 를 만 든 것 을 볼 수 있 지만 37 시 에 goto 가 5 가 되 었 고 순환 과정 에서 최적화 되 지 않 아 새로운 StringBuilder 를 계속 만 들 고 있다.그래서 상기 코드 는 유사 합 니 다.
String result = "";
for (int i = 0; i < 10; i++) {
StringBuilder tmp = new StringBuilder();
tmp.append(result);
tmp.append("some more data");
result = tmp.toString();
}
System.out.println(result);
새로운 StringBuilder 가 계속 생 성 되 고 tostring 을 통 해 원래 의 StringBuilder 는 더 이상 인용 되 지 않 으 며 쓰레기 로 서 GC 비용 도 증가 합 니 다.따라서 실제 사용 에 서 는 문자열 이 정적 연결 인지 동적 연결 인지 구분 할 수 없 을 때 StringBuilder 를 사용 하 세 요.
Reference:
http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
jdk8의datetime 시간 함수 사용 예시JDK8이 발표되었습니다.datetime 시간 함수 사용 방법의 작은 예시를 썼습니다 실행 결과...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.