우와한 개발자

[Java] 문자열 클래스(String, StringBuffer, StringBuilder)

by 우와한개발자

[ 문자열 클래스 ]

구분 String StringBuffer StringBuilder
변경 가능 여부 ❌ 불변(immutable) ✅ 가변(mutable) ✅ 가변(mutable)
스레드 안전성 ✅ 안전(불변이라) ✅ 안전(synchronized) ❌ 안전하지 않음
성능(문자열 수정/누적) ❌ 느림(매번 새 객체 생성) ⭕ 보통(락 오버헤드) ✅ 빠름(락 없음)
사용 목적 문자열 “값” 자체, 변경 거의 없음 멀티스레드 환경에서 문자열 누적/수정 단일 스레드에서 문자열 누적/수정
내부 동작 +/concat() 시 새 String 생성 내부 char 배열(버퍼) 확장하며 수정 내부 char 배열(버퍼) 확장하며 수정
equals 비교 ✅ 값 비교 ❌(기본 Object equals: 참조) ❌(기본 Object equals: 참조)
대표 예시 "a" + "b" 결과 new StringBuffer().append(...) new StringBuilder().append(...)
멀티스레드 추천

 

1. String

  • 불변(immutable) 클래스
  • 연산이나 concat() 을 쓸 때마다 새로운 String 객체가 생성
  • String 클래스 주요 메서드
메서드 반환 타입 설명 예시
charAt(int index) char 주어진 index 위치의 문자를 반환 "hello".charAt(1); // 'e'
compareTo(String anotherString) int 두 문자열을 사전(유니코드) 순서로 비교(같으면 0, 앞이면 음수, 뒤면 양수) "abc".compareTo("abd"); // -1
concat(String str) String 현재 문자열 뒤에 str을 연결한 새 문자열 반환 "hello".concat(" world"); // "hello world"
contains(CharSequence s) boolean 문자열에 s가 포함되어 있는지 여부 "hello".contains("ell"); // true
equals(Object anObject) boolean 두 문자열의 내용이 같은지 비교(대/소문자 구분) "Java".equals("java"); // false
equalsIgnoreCase(String anotherString) boolean 대/소문자 무시하고 두 문자열이 같은지 비교 "Java".equalsIgnoreCase("java"); // true
format(Locale l, String format, Object... args) static String 로케일과 포맷 문자열을 이용해 문자열 생성 String.format(Locale.KOREA, "%,d", 10000); // "10,000"
format(String format, Object... args) static String 기본 로케일로 포맷 문자열을 이용해 문자열 생성 String.format("Hello %s (%d)", "Tom", 3); // "Hello Tom (3)"
getBytes() byte[] 문자열을 플랫폼 기본 문자셋으로 인코딩한 바이트 배열 반환 byte[] b = "hi".getBytes(); // 예: [104, 105]
getBytes(String charsetName) byte[] 문자열을 지정한 문자셋으로 인코딩한 바이트 배열 반환 byte[] b = "가".getBytes("UTF-8");
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) void 문자열의 일부(srcBegin~srcEnd-1)를 dst 배열의 dstBegin부터 복사 char[] dst = new char[5]; "hello".getChars(1, 4, dst, 0); // dst[0..2] = 'e','l','l'
indexOf(int ch) int 문자(ch)가 처음 등장하는 인덱스(없으면 -1) "hello".indexOf('l'); // 2
indexOf(int ch, int fromIndex) int fromIndex 이후로 문자(ch)가 처음 등장하는 인덱스 "hello".indexOf('l', 3); // 3
indexOf(String str) int 부분 문자열 str이 처음 등장하는 인덱스 "hello".indexOf("ll"); // 2
indexOf(String str, int fromIndex) int fromIndex 이후로 부분 문자열 str이 처음 등장하는 인덱스 "hello".indexOf("l", 3); // 3
isEmpty() boolean 길이가 0이면 true 반환 "".isEmpty(); // true
length() int 문자열 길이 반환 "hello".length(); // 5
matches(String regex) boolean 문자열 전체가 주어진 정규표현식 regex와 일치하는지 확인 "010-1234-5678".matches("\\d{3}-\\d{4}-\\d{4}"); // true
replace(char oldChar, char newChar) String 문자열에서 oldChar 문자를 newChar로 바꾼 새 문자열 반환 "hello".replace('l', 'x'); // "hexxo"
replaceAll(String regex, String replacement) String 정규표현식 regex에 일치하는 모든 부분을 replacement로 치환 "a1b2c3".replaceAll("\\d", ""); // "abc"
split(String regex) String[] 정규표현식 regex 기준으로 문자열을 분리해 배열로 반환 "a,b,c".split(","); // ["a","b","c"]
substring(int beginIndex) String beginIndex부터 끝까지 부분 문자열 반환 "hello".substring(2); // "llo"
substring(int beginIndex, int endIndex) String beginIndex부터 endIndex-1까지 부분 문자열 반환 "hello".substring(1, 4); // "ell"
toLowerCase() String 소문자로 변환한 새 문자열 반환 "Java".toLowerCase(); // "java"
toUpperCase() String 대문자로 변환한 새 문자열 반환 "Java".toUpperCase(); // "JAVA"
trim() String 문자열 앞/뒤 공백 제거한 새 문자열 반환 " hi ".trim(); // "hi"

 

2. StringBuffer

  • thead-safe하고 mutable한 문자열 클래스
  • 내부적으로 synchronized가 걸려 있어 여러 스레드가 동시에 접근해도 안전

 

3. StringBuilder

  • mutable한 문자열 클래스
  • thread-safe하지 않아 동기화가 없어 StringBuffer보다 빠름

 

  • StringBuffer와 StringBuilder의 주요 메서드
메서드  반환 타입 설명 예시
append(String str) StringBuffer / StringBuilder 문자열 뒤에 str 추가 sb.append(" world");
charAt(int index) char 지정 위치의 문자 반환 sb.charAt(1); // 'e'
delete(int start, int end) StringBuffer / StringBuilder start ~ end-1 범위 문자열 삭제 sb.delete(1, 3);
deleteCharAt(int index) StringBuffer / StringBuilder 지정 위치의 문자 1개 삭제 sb.deleteCharAt(0);
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) void 문자열 일부를 배열로 복사 sb.getChars(1,4,arr,0);
indexOf(String str) int 부분 문자열 시작 인덱스 반환 (없으면 -1) sb.indexOf("ll"); // 2
insert(int offset, String str) StringBuffer / StringBuilder 지정 위치에 문자열 삽입 sb.insert(2,"XX");
length() int 문자열 길이 반환 sb.length();
replace(int start, int end, String str) StringBuffer / StringBuilder start ~ end-1 범위를 str로 교체 sb.replace(1,4,"abc");
reverse() StringBuffer / StringBuilder 문자열 순서 뒤집기 sb.reverse();
substring(int beginIndex) String beginIndex부터 끝까지 문자열 반환 sb.substring(2);
substring(int beginIndex, int endIndex) String beginIndex ~ endIndex-1 문자열 반환 sb.substring(1,4);
⚠️ thread-safe
- 여러 스레드가 동시에 접근해도 내부적으로 락(lock)을 걸어 한 번에 한 스레드만 변경 작업을 수행하도록 보장하는 것.
- 데이터가 꼬이거나 깨지는 문제(data race)를 막아줌

 

4. StringTokenizer

  • 문자열을 분리하기 위한 클래스
StringTokenizer st = new StringTokenizer(String str);

StringTokenizer st = new StringTokenizer(String str, String delim);

StringTokenizer st = new StringTokenizer(String str, String delim, boolean returnDelims);
  • 구분자 delim : 주어진 delim 문자열의 각 문자로 구분하여 객체 생성.
  • returnDelims : 구분자를 토큰에 포함할지 여부(기본값 false=포함❌)
⚠️ 문자열이 아닌 문자로 나누기 떄문에 특정 문자열 전체를 구분자로 사용하려면 split()사용.
  • StringTokenizer 클래스의 주요 메서드
메서드 반환 타입 설명 예시
countTokens() int 남아있는 토큰의 개수 반환 new StringTokenizer("a b c").countTokens(); // 3
hasMoreElements() boolean 더 읽을 요소가 있는지 확인 (hasMoreTokens()와 동일 의미) st.hasMoreElements();
hasMoreTokens() boolean 더 읽을 토큰이 있는지 확인 st.hasMoreTokens(); // true
nextElement() Object 다음 토큰 반환 (nextToken()과 동일하지만 반환 타입이 Object) st.nextElement();
nextToken() String 다음 토큰을 문자열로 반환 st.nextToken();
nextToken(String delim) String 구분자(delim)를 변경하여 다음 토큰 반환 st.nextToken(",");

 

5. split() 메서드

String[] splits = 문자열.split(String regex);

String[] splits = 문자열.split(String regex, int limit)
  • regex : 정규 표현식
  • limit : 반환할 문자열 배열의 크기

블로그의 정보

우와한개발자 님의 블로그

우와한개발자

활동하기