StringTokenizer, StringBuffer & StringBuilder 클래스

Donguk Lee·2021년 7월 20일
0

CodingTest

목록 보기
1/1

백준 코딩테스트 10950번 A+B - 3을 풀다 어쩌다보니 문자열을 주어진 매개변수 기준에 따라 쪼개는 split 메소드를 알게 되었고 구글링을 하다가 효율이 더 좋은 StringTokenizer 클래스를 보게 되어 이것이 자바다 책을 다시 꺼내 들었다.

국비 과정 도중 지나간 부분이라 보지 못했던 내용이라 다시 꼼꼼하게 읽고 공부한 김에 포스트를 남기려 한다.


11.8 StringTokenizer 클래스


문자열이 특정 구분자(delimeter)로 연결되어 있을 경우, 구분자를 기준으로 부분 문자열을 분리하기 위해서는 String의 split() 메소드를 이용하거나 java.util 패키지의 StringTokenizer 클래스를 이용할 수 있다.



11.8.1 split() 메소드

스플릿은 간단하다.

String text = "홍길동&이수홍,박연수-최명호";

String[] names = text.split("&|,|-");

정규표현식이 된다는 점은 개인적으로는 파이프 기호(|)로 분리가 모두 강력하다는 점은 강력하다고 생각된다.



11.8.2 StringTokenizer 클래스

StringTokenizer는 한 종류의 구분자로 연결되어 있을 경우, 사용이 더 쉽다. 사용법은 다음과 같다.

StringTokenizer st = new StringTokenizer("문자열", "구분자");

첫번째 매개변수는 분리할 문자열이며, 두번째 매개변수는 구분자를 넣어주면 된다. 구분자를 생략하면 공백(Space)이 기본 구분자가 된다. 다음은 StringTokenizer 를 통해 토큰을 관리할 수 있는 메소드들이다.

메소드 리턴타입메소드설명
intcountTokens()꺼내지 않고 남아 있는 토큰의 수
booleanhasMoreTokens()남아 있는 토큰이 있는지 여부
StringnextToken()토큰을 하나씩 꺼내옴

구분자에 의해 구분되는 덩어리들을 토큰(Token)이라고 부르며 nextToken() 메소드로 하나씩 꺼내올 수 있다. 꺼내오다가 토큰이 없으면 java.util.NoSuchElementException 예외를 발생시키므로 List에서 데이터를 꺼내오는 반복자 Iterator를 사용할 때 처럼 hasMoreTokens()로 확인하며 사용하는 것이 좋은 코딩 방법이다.



예제

String text = "홍길동/이수홍/박연수";

	//how1: 전체 토큰 수를 얻어 for문으로 루핑
	StringTokenizer st = new StringTokenizer(text, "/");
	int countTokens = st.countTokens();
	for(int i=0; i<countTokens; i++) {
		String token = st.nextToken();
		System.out.println(token);
	}

	System.out.println();

	//how2: 남아 있는 토큰를 확인하고 while문으로 루핑
	st = new StringTokenizer(text, "/");
	while( st.hasMoreTokens() ) {
		String token = st.nextToken();
		System.out.println(token);
	}
    
    // 결과 * 2
    // 홍길동
    // 이수홍
    // 박연수



11.9 StringBuffer & StringBuilder 클래스

이 클래스도 코딩 테스트 공부를 하다 우연히 보게 되어 알게 된 김에 함께 정리해보려고 한다.

문자열을 저장하는 String은 내부 문자열을 수정할 수 없다. 예를 들어 String의 replace() 메소드는 내부의 문자를 대치하는 것이 아니라, 대치된 새로운 문자열을 리턴한다. String 객체를 + 연산할 경우에도 마찬가지다.

한 마디로 객체를 만들어서 관리하는 String을 자주 연산하게 되는 방식은 비효율적이다.(이고잉님의 객체지향 프로그래밍에서 다루었던 왜 equals를 써야 비교가 되는지에 대한 내용과 얼추 연관되는 이야기같다.)

문자열을 결합하는 + 연산자를 많이 사용하면 할수록 구만큼 String 객체의 수가 늘어나기 때문에, 프로그램 성능을 느리게 하는 요인이 된다. 문자열을 변경하는 작업이 많을 경우에는 String 클래스를 사용하는 것보다는 java.lang 패키지의 StringBuffer 또는 StringBuilder 클래스를 사용하는 것이 좋다. 이 두 클래스는 내부 버퍼(buffer:데이터를 임시로 저장하는 메모리)에 문자열을 저장해 두고, 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다.

StringBuffer와 StringBuilder의 사용 방법은 동일하지만 멀티 스레드 환경에서 안전한지에 따른 차이점이 있다. StringBuffer는 멀티스레드 환경에서 사용할 수 있도록 동기화가 적용되어 있어 스레드에 안전하고, StringBuilder는 안전하지 않다.

StringBuilder 클래스는 다음과 같은 몇가지 생성자를 제공한다.

String sb = new StringBuilder();			// 16개의 문자들을 저장할 수 있는 초기 버퍼 내장.
String sb = new StringBuilder(30);			// 30개의 초기 버퍼 크기 설정
String sb = new StringBuilder("java");		// java라는 문자열을 버퍼의 초기값으로 설정한다.

StringBuilder의 버퍼 크기는 부족할 경우 늘어나기 때문에 크기 설정은 그다지 중요하지 않다.

다음은 버퍼 내에서 문자 추가, 삽입, 삭제 등의 작업을 할 수 있게 만드는 메소드들이다.

메소드설명
append(...)문자열 끝에 주어진 매개값을 추가
insert(int offset,...)문자열 중간에 주어진 매개값을 추가
delete(int start, int end)문자열의 일부분을 삭제
deleteCharAt(int index)문자열에서 주어진 index의 문자를 삭제
replace(int Start, int End, String str)문자열의 일부분을 다른 문자열로 대치
reverse()문자열의 순서를 뒤바꿈
setCharAt(int index, char ch)문자열에서 주어진 index의 문자를 다른 문자로 대치



예제

		StringBuilder sb = new StringBuilder();
		
		sb.append("Java ");
		sb.append("Program Study");
		System.out.println(sb.toString());
		
		sb.insert(4, "2");
		System.out.println(sb.toString());

		sb.setCharAt(4, '6');
		System.out.println(sb.toString());
		
		sb.replace(6, 13, "Book");
		System.out.println(sb.toString());
		
		sb.delete(4, 5);
		System.out.println(sb.toString());
		
		int length = sb.length();
		System.out.println("총문자수: " + length);
		
		String result = sb.toString();
		System.out.println(result);	

정리

StringTokenizer는 문자열을 분리하여 사용할 때, StringBuffer & StringBuilder는 문자열에 잦은 변경이 필요한 로직에 사용하면 좋을 듯하다. 또한, StringBuffer는 멀티 스레드 환경에서 안전하다. 기억해두고 코딩테스트 문제에서 활용해보도록 하자.

다음은 BufferedReader와 BufferedWriter에 대해서 다루어 보려고 한다.

profile
많은 이동욱 중 이름을 남기고 싶은 웹 개발 공부를 시작한 갓난이 개발자

0개의 댓글