티스토리 뷰
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
String Pool
the special memory region where Strings are stored by the JVM
위는 String Pool을 한 문장으로 설명한 것이다. 해석하면 JVM에 의해 문자열이 저장되는 특별한 메모리 공간이다. Java에서 문자열은 immutability를 가진다. 따라서 JVM은 String Pool을 사용하여 문자열 리터럴의 값을 하나만 저장하는 방식으로 메모리를 최적화 할수 있다. 이런 과정을 interning이라고 한다.
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
위의 코드를 사용해서 설명을 하겠다. 처음에 문자열 리터럴 s1을 생성했을 때 String Pool에 s1의 값 hello가 저장된다. 그리고 s1은 String Pool 문자열의 레퍼런스를 가진다.
s2를 생성할 때 String Pool을 우선 확인한다. 그리고 String Pool에 s2의 값이 있다면 해당 값의 레퍼런스를 리턴하고, 아니라면 String Pool에 새로운 값을 저장하고 새로 생성한 값을 리턴한다. 해당 코드에서는 hello가 있기 때문에 s2는 hello의 레퍼런스를 가진다.
s3는 이전과 다르다. s3은 문자열 리터럴이 아닌 new String을 사용하여 문자열 객체를 생성한다. 이 값은 String Pool이 아닌 힙 영역에 저장된다.
따라서 위의 그림이 완성, s1==s2는 true이고 s1==s3는 false가 나오게 되는 것이다. 만약 s3를 String Pool에서 가져오고 싶다면 어떻게 할까?
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello").intern();
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
s3를 String Pool에서 가져오고 싶다면 intern() 함수를 뒤에 붙여주면 된다. 위의 코드를 실행하면 s1==s3 또한 true가 출력된다.
이런 String Pool은 immutable한 문자열에서 메모리를 효율적으로 사용할 수 있게 도와준다. 만약 mutable한 문자열을 처리하고 싶다면 어떻게 하는 것이 좋을까? mutable한 문자열은 StirngBuffer 혹은 StringBuilder을 사용하면 된다.
StringBuffer VS StringBuilder
위 둘의 차이는 StringBuffer is synchronized, StringBuilder is not. 라고 stackoverflow에서 한 문장으로 설명한다. StringBuffer은 동기화된다는 뜻인데, 이런 특징으로 StringBuffer은 다중 스레드 환경에서 안전하다. 하지만, StringBuilder는 이런 동기화 과정이 없기 때문에 StringBuffer보다 더 빠르다는 장점이 있다.
int N = Integer.MAX_VALUE;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println("[StringBuffer]" + (System.currentTimeMillis() - t));
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println("[StringBuilder]" + (System.currentTimeMillis() - t));
}
위의 코드를 실행하면 StringBuffer에서 2배의 시간이 걸린것을 알 수 있다.
나는 알고리즘 문제를 해결할 때 StringBuilder을 사용하는데 위와 같이 시간면에서 성능 차이가 나기 때문이다. 그래서 알고리즘 문제를 풀 때 개인적으로 StringBuffer보다는 StringBuilder를 사용하는 것을 추천한다.
참고 자료
- Total
- Today
- Yesterday
- postman collection
- git
- pm.test
- pm.expect
- downTo
- 1차 인터뷰
- squash merge
- Basic Type
- Squash and merge
- 주생성자
- java
- string
- DGS Framework
- Kotlin
- Kotlin In Action
- hashcode
- 확장 함수
- postman tests
- 코딩테스트
- postman
- Python
- mysql
- python3
- github
- graphql
- 코틀린
- 네이버 2022 공채
- solidity
- go 특징
- 2차 인터뷰
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |