[Java] String 그리고 StringBuilder 그리고 StringBuffer?

Kim Ju Young·2022년 2월 4일
0

Java

목록 보기
2/2
post-thumbnail

시작하기 전에

StringBuilder를 쓸 줄 알아야 알고리즘 문제에서 편하게 써먹을 수 있다.

면접을 볼 때도 StringBuilder와 String의 차이를 알면 잘 답변할 수 있다.

해서 이번 글에선 String과 StringBuilder의 차이를 알아보려고 한다.

String

Java의 기본형에는 총 8가지가 있다.

종류자료형범위크기
논리형booleanfalse, true1byte
문자형char\u0000 ~ \ufffff (0~65,535)2byte
정수형byte-128 ~ 1271byte
''short-32,768 ~ 32,7672byte
''int-2,147,483,648 ~ 2,147,483,6474byte
''long-9,223,372,036,854,775,808 ~ -9,223,372,036,854,775,8088byte
실수형float1.4E-45 ~ 3.4E384byte
''double4.9E-324 ~ 1.8E3088byte

1.4E-45 같은 표기는 E 앞인 1.4 에 10을 -45번 곱하라는 소리다.
-45번은 1/10을 45번 곱하라는 소리다.

엥? 그런데 기본형 String이 어딨죠? 라고 물을 수 있다. String은 자바 기본형이 아니다. 기본형의 특징을 지닌 참조형이다. 기본형의 특징은 다음에서 볼 수 있다.

String str = "abc";

원래 클래스를 사용하고 객체를 생성하기 위해선 다음과 같이 해야한다.

String str = new String("abc");

하지만, 이렇게 하지 않고도 생성할 수 있으니 기본형의 특징을 가지고 있지만 참조형이라는 특이한 녀석이 되는 것이다. 참조형이란 단어를 잘 모르겠다면 네이버 블로그를 참고해라.

Oracle의 String 공식문서를 읽어보면 다음 같은 사실을 알 수 있다.

String 요약

  • Java 프로그램의 모든 문자열 리터럴(ex. "abc")은 이 클래스의 인스턴스로 구현됩니다.
  • 문자열은 일정합니다. 값을 만든 후에는 변경할 수 없습니다.
  • 문자열 버퍼는 변경 가능한 문자열을 지원합니다.
  • String 객체는 변경할 수 없으므로 공유할 수 있습니다.

여길 보면 두 번째에 좀 이상한 문구가 써있다. 문자열은 일정하고 값을 만든 후에는 변경할 수 없습니다?

String abc = "acv";
abc = abc + "asdfasdf";

이걸보면 변수 abc는 변경되는걸 볼 수 있는데, 문자열을 변경할 수 없다고 한다?

아하! abc는 문자열이 아니라 문자열 변수라는 걸 알 수 있고 "abc"와 "asdfasdf"이 바로 사라지지 않고 값을 변경할 수 없는 문자열이라는 걸 알 수 있다.

String이 할 수 있는 일

  • String에는 시퀀스의 개별 문자를 검사할 수 있다. (charAt)
  • 문자열을 비교할 수 있다. (compareTo)
  • 문자열을 검색할 수 있다. (contains, indexOf)
  • 하위 문자열을 추출할 수 있다. (substring)
  • 모든 문자가 대문자 또는 소문자로 변환된 문자열의 복사본을 만들 수 있다. (toLowerCase, toUpperCase)

String은 문자열 자체를 변경하거나 삭제할 수 없다. 그저, 다른 문자열을 만들어주기 위해선 어떤 문자열에서 문자열을 추출해서 객체를 생성해내거나 복사하는 것이다.

String은 값을 변경할 수 없는 문자열 객체를 생성한다. 만약, 내가 어떤 문자열을 사용자에게서 입력받았고, 그걸 조작한 값들을 출력하려면 어떻게 해야 될까?

여기선, 값을 마지막 문자를 제거한 값이 필요하다고 가정하자.

나는 "abcd", "sdlfsl", "pelix", "maven" 이라는 단어를 입력했다. 마지막 문자를 제거하기위해 문자열을 마지막 문자만 빼고 추출하는 substring메소드를 사용했다.

내가 필요한 값은 "abc", "sdlfs", "peli", "mave"인데 "abcd", "sdlfsl", "pelix", "maven" 값 또한 메모리 영역을 차지하고 있다.

즉, 문자열 추가,수정,삭제 등의 연산이 빈번하게 발생하는 알고리즘일 때 String을 사용하면 heap 메모리를 낭비하게 된다는 거다.

StringBuilder

StringBuilder는 String을 보완하여 heap 메모리에 있는 문자열을 변경할 수 있다.

StringBuilder sb= new StringBuilder("hello"); 
sb.append(" world");

원래 String을 사용했더라면 "hello"와 " world", "hello world" 까지 해서 총 3개의 문자열을 생성이 됐을 테지만 StringBuilder로 생성하고 문자열을 더했더니 1개 문자열만 가지게 되었다.

메모리를 차지하는게 적기 때문에 문자열 연산을 많이 할 수 있겠다.

그 이점을 살리기 위해 append와 insert, delete 연산을 추가로 제공한다.

  • append(a) : 문자열 데이터의 추가, a를 뒤에 이어붙여준다.
  • insert(a, b) : 중간 문자열 삽입, 대체로 a가 offset이고 b는 삽입할 데이터이다.
  • deleteCharAt(a) : 중간 char 하나만 삭제할 수 있다.

StringBuffer?

StringBuffer는 StringBuilder와 같지만, 멀티스레드 환경까지 지원한다. IfUWanna님이 쓴 글을 인용하겠다.

가장 큰 차이점은 동기화의 유무로써 StringBuffer는 동기화 키워드를 지원하여 멀티쓰레드 환경에서 안전하다는 점(thread-safe) 입니다. 참고로 String도 불변성을 가지기때문에 마찬가지로 멀티쓰레드 환경에서의 안정성(thread-safe)을 가지고 있습니다.

StringBuilder는 대신 단일스레드 환경에서 StringBuffer보다 성능이 좋다는 장점을 갖는다.

마무리하며

정리
String : 문자열 연산이 적고 멀티쓰레드 환경일 경우
StringBuffer : 문자열 연산이 많고 멀티쓰레드 환경일 경우
StringBuilder : 문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우

이번 기회에 StringBuilder 뿐만 아니라 StringBuffer와의 차이점 또한 알게되어 소득이 있다. 그저 알고리즘 문제에서 "String엔 왜 마지막 문자 제거나 문자 추가가 구현되어 있지 않지!? 귀찮구만~" 라는 의문에서 시작한 글 치고는 얻어가는게 많았던 것 같다.

보는 분들도 많이 얻어가셨으면 좋겠다.

참고

String 공식문서
참조 형(Reference Type)과 참조 변수(Reference Variable) - 이구자바님
[Java] String, StringBuffer, StringBuilder 차이 및 장단점 - IfUWanna님

profile
호호선생

0개의 댓글