String에 "를 추가하면 메모리가 절약되는 이유는 무엇입니까?
, 를 들어 '를 사용했는데요.String data
사용하고
this.smallpart = data.substring(12,18);
( 비주얼라이저를 디버깅을 몇 동안 필드('메모리 비주얼라이저가 되었습니다.smallpart
데이터를 기억하다data
만
코드를 다음과 같이 변경했을 때:
this.smallpart = data.substring(12,18)+"";
..문제가 해결되었다!이제 내 앱은 메모리를 거의 사용하지 않습니다!
어떻게 그것이 가능한가요?누가 이걸 설명할 수 있나요?제 생각엔 작은 부분은 계속 데이터를 참조하는데, 왜일까요?
업데이트: 그러면 큰 문자열을 지우려면 어떻게 해야 합니까?data = new String(data.substring(0,100))이 작업을 수행할 수 있습니까?
다음을 수행합니다.
data.substring(x, y) + ""
는 새로운 (더 작은) String 객체를 생성하여 서브스트링()에 의해 작성된 String에 대한 참조를 폐기함으로써 가비지 수집을 newable로 합니다.
깨달아야 할 중요한 것은substring()
는 기존 String(또는 원래 String의 기초가 되는 문자 배열)에 대한 창을 보여줍니다.따라서 원래 String과 동일한 메모리를 사용합니다.이것은 경우에 따라서는 편리할 수 있지만, 서브스트링을 취득해 원래의 String을 폐기하는 경우는 문제가 있습니다(알고 있듯이).
자세한 내용은 JDK String 소스의 substring() 메서드를 참조하십시오.
편집: 보충 질문에 답하기 위해 서브스트링에서 새로운 String을 작성하면 원래 String에 대한 참조를 모두 삭제하면 메모리 소비량이 줄어듭니다.
참고 (2013년 1월)위의 동작은 Java 7u6에서 변경되었습니다.Flyweight 패턴은 더 이상 사용되지 않습니다.substring()
예상대로 동작합니다.
의 substring(int, int)
뭇매를 맞다
new String(offset + beginIndex, endIndex - beginIndex, value);
서 ''는value
원조입니다.char[]
그러면 새로운 String을 얻을 수 있지만 기본은 동일합니다.char[]
.
경우, ★★★★★★★★★★★★★★★★.data.substring() + ""
, 새로운 기반이 되는 새로운 String을 얻을 수 있습니다.char[]
.
는 '사용 사례', '사용 사례', '사용 사례', '사용 사례', '사용 사례', '사용 사례', ' 사례'만.String(String)
★★★★★★★★★★★★★★★★★★:
String tiny = new String(huge.substring(12,18));
「 」를 사용하는 substring
새 문자열은 실제로 생성되지 않습니다.여전히 오프셋 및 크기 제약이 있는 원래 문자열을 참조합니다.
원래 수 새 .new String
것 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
제 생각엔 작은 부분은 계속 데이터를 참조하는데, 왜일까요?
자바 문자, 해시 코드(hash Code) 문자oper음음음음ationsationsationsations 등의 문자열 .substring()
원본의 문자 배열을 공유하고 오프셋 및/또는 길이 필드가 서로 다른 새 문자열 개체를 만듭니다.이것은 String의 char 배열이 작성된 후에는 변경되지 않기 때문에 작동합니다.
이렇게 하면 중복되는 부분을 복제하지 않고 많은 서브스트링이 동일한 기본 문자열을 참조할 때 메모리를 절약할 수 있습니다.이미 알고 있듯이 상황에 따라 더 이상 필요하지 않은 데이터가 수집되지 않도록 할 수 있습니다.
하는 '은 '올바른' 방법입니다.new String(String)
스트럭럭 、 ★
this.smallpart = new String(data.substring(12,18));
BTW, 가장 좋은 해결책은 처음부터 매우 큰 문자열이 있는 것을 피하고 작은 청크(aa 몇 KB)로 입력을 처리하는 것입니다.
Java 문자열은 변경할 수 없는 개체이며, 문자열이 생성되면 가비지 콜렉터에 의해 지워질 때까지 메모리에 남아 있습니다(이 클리닝은 당연하게 받아들일 수 없습니다).
서브스트링 메서드를 호출하면 Java는 완전히 새로운 문자열을 작성하지 않고 원래 문자열 안에 문자 범위만 저장합니다.
따라서 다음 코드를 사용하여 새 문자열을 작성했을 때:
this.smallpart = data.substring(12, 18) + "";
결과를 빈 문자열과 연결하면 실제로 새 문자열이 생성됩니다.그래서 그런 거야.
1997년 jwz에 의해 문서화된 바와 같이:
큰 문자열이 있는 경우 그 서브스트링()을 꺼내서 서브스트링을 잡고 긴 문자열이 가비지(즉, 큰 문자열의 기본 바이트가 사라지지 않습니다).
요약하자면, 소수의 큰 문자열로 많은 서브스트링을 작성하면
String subtring = string.substring(5,23)
큰 끈을 저장하는 데만 공간을 사용하지만, 큰 끈의 손실에서 작은 끈을 몇 개만 추출할 경우,
String substring = new String(string.substring(5,23));
대용량 문자열은 더 이상 필요하지 않을 때 재확보할 수 있으므로 메모리 사용량을 줄일 수 있습니다.
것은 '아예'new String
는 원래 문자열에 대한 참조가 아니라 실제로 새 문자열을 얻을 수 있음을 알려주는 데 도움이 됩니다.
첫째, 호출하면 기본 배열의 중요한 부분을 복사하는 대신 오프셋과 길이를 사용하여 원본에 새 창이 생성됩니다.
더 자세히 보면substring
메서드는 문자열 생성자 호출에 주목합니다.String(int, int, char[])
통째로 넘기고char[]
스트링을 나타냅니다.즉, 서브스트링이 원래 문자열과 같은 양의 메모리를 차지합니다.
왜 래, 데는 거죠?+ ""
메모리가 없는 경우보다 더 적은 메모리가 필요합니까?
을다하 +
strings
통해 됩니다.StringBuilder.append
에 이 방법의 .AbstractStringBuilder
' 하다'는 것을 거예요.arraycopy
됩니다.substring
를 참조해 주세요.
다른 해결 방법은?
this.smallpart = new String(data.substring(12,18));
this.smallpart = data.substring(12,18).intern();
문자열에 "를 추가하면 메모리가 절약될 수 있습니다.
책 한 권이 들어 있는 큰 끈이 있다고 칩시다. 백만 글자에요.
그리고 책의 각 장을 밑줄로 한 20개의 줄을 만듭니다.
그러면 모든 단락을 포함하는 1000개의 문자열을 만듭니다.
그리고 모든 문장을 포함하는 10,000개의 문자열을 만듭니다.
그리고 모든 단어를 포함하는 100,000개의 문자열을 만듭니다.
저는 아직 100만 글자밖에 안 써요.각 장, 단락, 문장, 단어에 "를 추가하면 500,000자를 사용할 수 있습니다.
물론 책 전체에서 한 단어만 뽑아낸다면 완전히 다를 수 있고, 책 전체가 쓰레기 수집품일 수도 있지만, 그 한 단어가 그 단어에 대한 언급을 가지고 있기 때문은 아닙니다.
또한 100만 개의 문자열이 있고 양 끝에 탭과 공백을 제거하여 하위 문자열을 생성하기 위해 10개의 호출을 하는 경우에도 다릅니다.Java가 동작하거나 동작하는 방식은 매번 백만 개의 문자를 복사하는 것을 방지합니다.타협이 있고, 타협이 무엇인지 아는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/2147783/why-does-appending-to-a-string-save-memory
'itsource' 카테고리의 다른 글
액티비티를 시작할 때 키보드가 표시되지 않도록 합니다. (0) | 2022.07.21 |
---|---|
Vuex 상태에서 nuxt '$config'에 액세스하는 방법액세스 방법만 스토어 액션 방식을 사용합니까? (0) | 2022.07.21 |
어떻게 하면 C 프리프로세서와 두 번 연결하여 "arg ##_# MACRO"처럼 매크로를 확장할 수 있습니까? (0) | 2022.07.21 |
Java에서 String에서 파일 확장자를 자르는 방법은 무엇입니까? (0) | 2022.07.21 |
Java에서 운영체제를 프로그래밍 방식으로 판별하려면 어떻게 해야 하나요? (0) | 2022.07.21 |