StringBuffer 클래스


문자열을 처리하는 클래스이다.

 

String 클래스와의 차이점

String 클래스는 내부 문자열 데이터의 수정이 불가능하지만 (String 클래스의 중요한 특징!! 불★변★)

StringBuffer 클래스는 문자열을 사용할 때 내부 문자열을 실행 단계에서 변경할 수 있다는 것이다.

StringBuffer 객체는 가변적인 길이를 가지므로 객체를 생성하는 시점에서 미리 그 크기나 값을 지정하거나 실행 시점에 버퍼의 크기를 바꿀 수 있는 기능을 제공한다. 

 

 

StringBuilder 클래스


JDK 1.5 이후부터는 문자열을 처리하는 StringBuilder 라는 클래스도 제공한다.
StringBuilder 클래스의 기능은 StringBuffer 클래스와 동일하지만 가장 큰 차이점은 multi-thread unsafe 라는 점이다.
즉, Synchronization(동기화) 이 없기 때문에 StringBuffer 보다 처리가 빠른 장점이 있다. 따라서 개발하는 프로그램이 동시성(동기화) 문제가 없다면 StringBuilder 클래스를 사용하는 것이 성능을 향상시킬 수 있다.

* 쓰레드(thread)는 지금 학습하는 눈높이에서 '작업의 단위' 정도로만 인식해두자.

 

※ 문자열을 다루는 클래스

String :          내용 변경Ⅹ - 안전하여 멀티 thread 환경에서 사용하기 좋음

StringBuffer :  내용 변경○. 동기화 지원○ - 멀티 thread 환경에서 사용(동시성). ex - 클라우드의 공용 문서작업

StringBuilder : 내용 변경○. 동기화 지원Ⅹ - 단일 thread 환경에서 사용. StringBuffer보다 성능 좋음.

 

 

StringBuffer 클래스 예제 코드 1  -  String 클래스와 StringBuffer 클래스 비교, StringBuffer 클래스의 메소드


※ StringBuffer 클래스의 주요 메소드

반환형

메소드이름(매개변수)

설명

String 

 toString()

 String 클래스의 문자열로 변환 
 ★toString을 통해 변환하면 String 클래스의 메소드을 사용할 수 있다.★
 ex) StringBuffer sb = new StringBuffer("abc");
      sb.toString().equals("ABC");    // false
      // StringBuffer 클래스에는 equals() 메소드 없음(오버라이딩 Ⅹ)

int

 capacity()

 StringBuffer의 버퍼 크기(적재량) 반환
 ex) StringBuffer sb = new StringBuffer();
      sb.capacity();    // 16
 ※ 매개변수 없이 생성한 StringBuffer의 기본 버퍼크기는 16 이다.

StringBuffer 

 append(Object obj)

 대상 문자열에 다른 문자열 등등 덧붙이기
 ex) StringBuffer sb = new StringBuffer("kim ");
      sb.append("soso");    // "kim soso"
 ※ String 클래스와 달리 '+'연산자로 덧붙일 수 없다.

StringBuffer 

 insert(int index, Object obj)

 문자열의 특정 위치(index)에 문자열 등등 삽입
 ex) StringBuffer sb = new StringBuffer("abcdefg");
      sb.insert(3, "ABC");    // "abcABCdefg"

StringBuffer 

 delete(int start, int end)

 문자열의 위치(index) start 부터 (end-1) 까지 삭제
 ex) StringBuffer sb = new StringBuffer("abc^^defg");
      sb.delete(3, 5);    // "abcdefg"
      sb.delete(4, sb.length());    // "abcd"

void

 trimToSize()

 버퍼 크기 조절. 현재 담긴 문자열에 맞춰서 조절된다.
 ※ 보통 크기를 줄일 때 사용(문자열이 길어지면 버퍼도 자동으로 늘어남)

 

+ 추가로 String 클래스의 메소드 2가지

반환형

메소드이름(매개변수)

설명

String 

 toUpperCase()

 대상 문자열의 영문자를 모두 대문자로 변환
 ex) "abc".toUpperCase();    // "ABC"

String 

 toLowerCase()

 대상 문자열의 영문자를 모두 소문자로 변환
 ex) "ABC".toUpperCase();    // "abc"

 

/*=====================================
  ■■■ 자바의 주요(중요)클래스 ■■■
  - StringBuffer 클래스
=====================================*/

public class Test143
{
	public static void main(String[] args)
	{
		StringBuffer sb1 = new StringBuffer("korea");
		StringBuffer sb2 = new StringBuffer("korea");

		System.out.println(sb1 == sb2);
		//--==>> false
		// '=='연산자는 오버라이딩의 개념이 없다. 무조건 주소값 비교
        
		System.out.println(sb1.equals(sb2));
		//--==>> false
		// String의 equals() 는 문자열 상수를 비교할 수 있도록 Object의 것을 오버라이딩 해둠
		// 결과를 통해 StringBuffer 클래스는 equals() 를 오버라이딩하지 않은 것으로 추측.
		// api 문서를 확인해보니 equals() 메소드 없음 → 지금 호출한 것은 Object의 equals()

		System.out.println(sb1);
		System.out.println(sb1.toString());
		//--==>> korea	// StringBuffer
		//	 korea	// StringBuffer.toString()
		// 결과를 통해 toString() 은 오버라이딩 했음을 알 수 있다.


		// ○ String 클래스의 메소드로 StringBuffer 객체 다루기
		System.out.println(sb1.toString().equals(sb2.toString()));
		//			       ---------------------		 ---------------------
		//		   		 String			     String
		//--==>> true
		// StringBuffer 는 toString()을 통해 얼마든지 String 클래스의 메소드 사용할 수 있다.

		
		// ○ StringBuffer 의 매개변수가 없는 생성자 호출(인스턴스 생성 과정)
		//   기본적으로 생성되는 버퍼 크기는 『16』
		StringBuffer sb3 = new StringBuffer();
		System.out.println(sb3);
		//--==>>        (無)
        
        
		// ○  StringBuffer 객체의 버퍼 크기 확인(적재량 확인)
		System.out.println("버퍼 크기 : " + sb3.capacity());
		//--==>> 버퍼 크기 : 16


		//----------------------  String 클래스  vs  StringBuffer 클래스  ----------------------
        
		// ○ StringBuffer 문자열에 다른 문자열 덧붙이기
		sb3.append("seoul");	// sb3 += "seoul";
		sb3.append("korea");	// 객체.append(s);
		sb3.append("우리나라");
		sb3.append("대한민국");

		System.out.println(sb3);
		System.out.println(sb3.toString());
		//--==>> seoulkorea우리나라대한민국
		//		 seoulkorea우리나라대한민국

		System.out.println("버퍼 크기 : " + sb3.capacity());
		//--==>> 버퍼 크기 : 34
		// 버퍼 크기가 자동으로 늘어났다. 그러나 버퍼 크기를 자동으로 줄여주지 않는다.
		// 버퍼 크기가 크면 메모리를 더 많이 소모한다.
        
		/* String 문자열에 다른 문자열 덧붙이기
			String name = "홍길동";
			name += "이순신";
			name += "강감찬";
			System.out.println(name);
			//--==>> 홍길동이순신강감찬
			*/

		//----------------------  String 클래스  vs  StringBuffer 클래스  ----------------------

		// ○ 영문자를 모두 대문자로 변환
		String temp1 = "java and oracle";	// String 객체임!
		System.out.println(temp1.toUpperCase());	// String객체.toUpperCase()
		//--==>> JAVA AND ORACLE
		// to~~~~~() >> '변환'의 기능을 하는 메소드 이름 특징


		// ○ 영문자를 모두 소문자로 변환
		String temp2 = "JAVA AND ORACLE";	// String 객체임!
		System.out.println(temp2.toLowerCase());	// String객체.toLowerCase()
		//--==>> java and oracle


		// ○ StringBuffer 객체의 영문자를 대문자 ↔ 소문자 변환
		//System.out.println(sb3.toUpperCase());
		//System.out.println(sb3.toLowerCase());
		//--==>> 에러 발생(컴파일 에러)
		// StringBuffer 클래스에는 toUpperCase, toLowerCase 메소드가 없다
        

		// ○ StringBuffer 객체의 영문자를 대소문자로 변환하기
		String temp3 = sb3.toString();	// StringBuffer 를 String 변환하여 새로 저장
		System.out.println(temp3.toUpperCase());
		//--==>> SEOULKOREA우리나라대한민국
		
		System.out.println(sb3.toString());	// StringBuffer 를 String으로 출력
		//--==>> seoulkorea우리나라대한민국
		//	 sb3 의 값은 바뀌지 않았음을 확인할 수 있다.
		//	 앞서 관찰한 대소문자 변환은 sb3 을 대상으로 한 게 아니라
		//	 String으로 변환한 객체를 대상으로 했다. check~!


		//----------------------  StringBuffer 클래스의 메소드 관찰  ----------------------

		// ○ 대상 문자열의 특정 위치(index)에 다른 문자열 삽입
		sb3.insert(0, "한국");	// 대상 문자열의 0번째 index에 문자열 "한국" 삽입
		System.out.println("seoul 앞에 『한국』 추가 : " + sb3.toString());
		//--==>> seoul 앞에 『한국』 추가 : 한국seoulkorea우리나라대한민국
		// sb3 에 저장된 값(내용)이 바뀜 → insert() 는 StringBuffer 의 메소드
        

		// ○ 대상 문자열(sb3) 중 korea 문자열 '뒤'에 문자열 " 사랑 " 삽입하기
		// 테스트 ① - 현재 sb3 의 내용
		System.out.println(sb3.toString());
		//--==>> 한국seoulkorea우리나라대한민국


		// 테스트 ② - 저장될 위치를 직접 카운팅하여 삽입하는 방법
		/*
			sb3.insert(12, " 사랑 ");
			System.out.println("korea 뒤에 『사랑』추가 : " + sb3.toString());
			//--==>> 한국seoulkorea 사랑 우리나라대한민국
			*/
		

		// 테스트 ③ - 대상 문자열에서 "korea" 문자열의 위치 찾기
		/*
			System.out.println(sb3.indexOf("korea"));
			//--==>> 7
			//	 StringBuffer 클래스에도 indexOf() 메소드가 오버라이딩되어 있다.
			*/


		// 테스트 ④ → 인덱스 7에 문자열 " 사랑 " 삽입
		/*
			System.out.println(sb3.insert(sb3.indexOf("korea"), " 사랑 "));
			//--==>> 한국seoul 사랑 korea우리나라대한민국
			*/


		// 테스트 ⑤ → 인덱스 12(인덱스 7 + 5)에 삽입
		// sb3.insert( ("korea"의 문자열인덱스 + "korea"문자열 길이), " 사랑 ");
		/*
			System.out.println(sb3.insert(sb3.indexOf("korea") + 5, " 사랑 "));
			//--==>> 한국seoulkorea 사랑 우리나라대한민국
			*/


		// 테스트 ⑥ → 마무리 정리
		sb3.insert(sb3.indexOf("korea") + "korea".length(), " 사랑 ");
		//         	  --------------------------7       --------------------5
		System.out.println(sb3);
		//--==>> 한국seoulkorea 사랑 우리나라대한민국



		// ○ 대상 문자열에서 부분 문자열 삭제
		// StringBuffer 클래스의 delete(s, e);	위치 index s 부터 (e-1) 까지 삭제
        
		// sb3.toString() == "한국seoulkorea 사랑 우리나라대한민국"
		sb3.delete(sb3.indexOf("우리나라"),
				sb3.indexOf("우리나라") + "우리나라".length());
		// 삭제시작위치 : "우리나라" index	삭제끝위치 : 시작위치 + 삭제할 index 갯수
		System.out.println(sb3);
		//--==>> 한국seoulkorea 사랑 대한민국
        
        
		/* 삭제할 문자열의 위치(index)를 직접 카운팅하여 삭제하는 방법
			sb3.delete(16, 20);
			System.out.println(sb3);
			//--==>> 한국seoulkorea 사랑 대한민국
			*/


		// ○ 대상 문자열에서 특정 문자열을 포함하여 끝까지 삭제
		// sb3.delete(s, sb3.length());	// 삭제끝위치 : 문자열의 길이
		sb3.delete(sb3.indexOf("korea"), sb3.length());
		System.out.println(sb3);
		//--==>> 한국seoul
		//	 + StringBuffer 클래스도 length() 메소드가 존재한다.


		// ○ 여러번의 StringBuffer 객체의 내용을 변경한 후의 버퍼 크기 확인
		System.out.println("버퍼 크기 : " + sb3.capacity());
		//--==>> 버퍼 크기 : 34
		// 내용이 줄어들었지만 버퍼 크기는 줄어들지 않았다. check~!


		// 문자열(sb3)의 길이 확인
		System.out.println("문자열의 길이 : " + sb3.length());
		//--==>> 문자열의 길이 : 7
		//	 버퍼의 크기와 문자열의 길이는 같지 않다.


		// ○ 버퍼 크기 조절하기
		// 현재 문자열을 담을 수 있는 사이즈로 조절된다. (버퍼를 줄이고 싶을 때 사용)
		// 담는 문자열(내용)이 길어지면 자동으로 버퍼의 크기도 늘어난다.
		sb3.trimToSize();

		// 버퍼 크기 조절 이후 버퍼의 크기 확인
		System.out.println("버퍼 크기 : " + sb3.capacity());
		//--==>> 버퍼 크기 : 7
	}
}

 

 

StringBuffer 클래스 예제 코드 2  -  문자열의 변경(대체, 삭제, 삽입) 예측과 관찰 (index 주의)


이번 예제 코드는 문자열의 일부를 대체하거나 삭제, 추출, 다른 문자열을 삽입한다.

문자열의 수정 결과를 미리 예측하는 연습을 하는 코드이다.

컴파일이나 주석을 보기 전에 인덱스에 특히 주의하며 예측 결과와 실제 결과를 비교해보자.

/*=====================================
  ■■■ 자바의 주요(중요)클래스 ■■■
  - StringBuffer 클래스
=====================================*/

// 문자열의 변경 내용을 보고 결과 예측해보기
        
public class Test144
{
	public static void main(String[] args)
	{
		// ○ String 문자열의 관찰
		String s1 = "123456789";
		s1 = (s1+"123").replace('2', 'A');
		System.out.println(s1);
        
		// "123456789" → "123456789123" → "1A34567891A3"
		//--==>> 1A34567891A3


		// ○ StringBuffer 문자열의 관찰
		StringBuffer s2 = new StringBuffer("123456789");
		s2.delete(0, 3).replace(1,3,"24").delete(4, 5);
		System.out.println(s2);
        
		// "123456789".delete(0, 3).replace(1,3,"24").delete(4, 5);
		// ------------------------"456789"
		// "456789".replace(1,3,"24").delete(4, 5);
		// ------------------------"424789"
		// "424789".delete(4, 5);
		// -------------------"42479"
		//--==>> 42479
		// 여기서의 replace()는 StringBuffer의 메소드. (api 문서를 통해 확인할 수 있다.)


		StringBuffer s3 = new StringBuffer("123456789");
		String s4 = s3.substring(3, 6);
		System.out.println(s4);
        
		// "123456789".substring(3, 6);
		//--==>> 456
		// 여기서의 substring()는 StringBuffer의 메소드. (api 문서를 통해 확인할 수 있다.)
		// StringBuffer 의 substring()은 추출된 문자열을 제외한 부분은 버린다(변경된다).
		// ※ 참고 : String 의 substring() 은 추출 문자열을 참고하여 새 String 객체로 반환

		
		StringBuffer s5 = new StringBuffer("123456789");
		s5.delete(0, 3).delete(1, 3).delete(2, 5).insert(1, "24");
		System.out.println(s5);
        
		// "123456789".delete(0, 3).delete(1, 3).delete(2, 5).insert(1, "24");
		// ----------------------"456789"
		// "456789".delete(1, 3).delete(2, 5).insert(1, "24");
		// -------------------"4789"
		// "4789".delete(2, 5).insert(1, "24");
		// -----------------"47"
		// "47".insert(1, "24");
		// ------------------"4247"
		//--==>> 4247
	}
}

 

 

 

 

StringTokenizer 클래스


문자열 파싱(parsing)을 위한 정보를 제공하는 클래스이다.

 

파싱(parsing)이란 하나의 문자열을 여러 문자열로 나누는 작업을 의미하며, 나누어진 문자열을 토큰(token)이라고 한다. StringTokenizer 클래스의 생성자는 파싱(parsing)하고자 하는 문자열을 인자로 받아 생성한다.

 

사실 문자열을 파싱하는 상황에서 StringTokenizer 클래스를 사용하기 보다는 String 클래스의 split() 메소드를 사용할 것을 권장한다. 그럼에도 StrinigTokenizer 클래스를 배우는(사용하는) 이유는 기존에 작성된 코드들을 문법적으로 호환하기 위해서이다.

우수한 문법이 지원되었다고 기존의 문법을 제한한다면, 기존의 문법으로 구축된 수 많은 소스코드들은 문제가 발생할 것이다. StringTokenizer 클래스보다 String 클래스의 split() 메소드가 성능, 편리성 등 우수하지만 기존에 작성된 코드의 호환성을 위해서 여전히 StringTokenizer 클래스를 지원한다고 할 수 있다.
+ 자바 언어의 학습 측면에서 StringTokenizer 클래스를 배우면, 이후에 배우는 컬렉션(collection)에서 iterator 나 immutable 을 이해하기 수월하다.

 

 

 - StringTokenizer 클래스는 java.util 패키지에 위치하므로 사용하기 위해서는 java.util 패키지의 StringTokenizer 를 import 해야 한다.

 - StringTokenizer 클래스는 호환성을 유지하는 목적으로 보관 유지되고 있으며, 문자열을 파싱(parsing)하기 위해서는 String 클래스의 split() 메소드나 java.util.regex 패키지를 사용할 것을 권장하고 있다.

 

StringTokenizer  생성자


StringTokenizer 클래스는 3가지의 생성자를 가진다.

1.  StringTokenizer(String str);

    : 공백을 기준으로 str 문자열을 나눈다.

2.  StringTokenizer(String str, String delim);

    : 구분자 String delim 을 기준으로 str 문자열을 나눈다.

3.  StringTokenizer(String str, String delim, boolean returnDelims);

    : 구분자 String delim 을 기준으로 str 문자열을 나눈다. 단, 세 번째 매개변수로 true 가 전달되면 구분자 또한 하나의 토큰으로 분리되며, false 가 전달될 때는 구분자는 토큰으로 분리하지 않는다.

String str = "red, blue, green, black and white";


// StringTokenizer 클래스의 생성자 3가지
StringTokenizer(String str);
StringTokenizer(String str, String delim);
StringTokenizer(String str, String delim, boolean returnDelims);

// 생성자 별로 토큰 구분 후 확인 (토큰과 토큰 사이는 '/' 로 구분했다.)

// 생성자 : StringTokenizer(String str);
토큰 수 : 6개
red,/blue,/green,/black/and/white/
//-- 공백을 기준으로 구분되었다.

// 생성자 : StringTokenizer(String str, ",");
토큰 수 : 4개
red/ blue/ green/ black and white/
//-- 구분자 ,(콤마)를 기준으로 구분되었다. 공백으로는 구분되지 않았다.

// 생성자 : StringTokenizer(String str, ",", true);
토큰 수 : 7개
red/,/ blue/,/ green/,/ black and white/
//-- 구분자 ,(콤마)를 기준으로 구분되었다. 공백으로는 구분되지 않았다.
//   구분자 ,(콤마) 또한 하나의 토큰으로 구분되었다.

// 생성자 : StringTokenizer(String str, ",", false);
red/ blue/ green/ black and white/
//-- 구분자 ,(콤마)를 기준으로 구분되었다. 공백으로는 구분되지 않았다.
//   구분자 ,(콤마) 는 토큰으로 구분되지 않았다.

 

 

StringTokenizer 클래스 예제 코드


※ StringTokenizer 주요 메소드

tokenizer 문자열에는 토큰을 가리키는 cursor(헤드) 가 존재한다.

hasMoreTokens() 메소드를 호출하여 cursor 가 이동할 수 있는지 없는지 확인하고(cursor(헤드) 이동 Ⅹ)

nextToken() 메소드를 호출하면 다음 토큰을 String으로 반환하고 cursor 가 (방금 반환된 토큰으로) 이동한다.

반환형 메소드이름(매개변수) 설명
int   countTokens()  파싱된 문자열(토큰)의 갯수를 int형으로 반환
 토큰 수 : nextToken() 메서드를 호출할 수 있는 횟수
 - 토큰의 수보다 많이 nextToken() 을 호출하면 예외가 발생함
boolean   hasMoreTokens()  파싱한 문자열에서 사용할 수 있는 토큰이 더 있는지 확인하여 true/false 반환
 현재 cursor(헤드) 위치 이후에 남은 토큰이 더 있는지 확인만 해주는 용도이다(망보는 역할). cursor(헤드) 의 이동은 발생하지 않는다.
 - nextToken() 메소드를 호출하기 전에 호출할 토큰이 남아있는지 확인
   true 를 반환한 상황 == 다음 토큰의 존재를 의미
                                  → nextToken() 호출하여 토큰 데이터 활용
String   nextToken()  다음 토큰을 반환한다.
 이때 cursor(헤드) 는 이동하여 현재 반환된 토큰을 가리킨다.
 구분자를 바꾸었을 경우, 다음 호출는 바뀐 구분자를 이용하여 토큰을 분리한다.
/*=====================================
  ■■■ 자바의 주요(중요)클래스 ■■■
  - StringTokenizer 클래스
=====================================*/

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.StringTokenizer;	// check~!!!

public class Test145
{
	public static void main(String[] args) throws IOException
	{
		String strTemp;		// 파싱할 문자열
		String[] strArr;	// 파싱 후 분리된 문자열(토큰)들을 저장할 배열
		int n;			// 파싱 후 배열 접근을 위한 변수

		// BufferedReader 기반의 인스턴스 생성
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		System.out.print("파싱할 문자열 입력(컴마구분) : ");
		strTemp = br.readLine();	//-- "사과,딸기,바나나"

		// 테스트(확인) - 파싱할 문자열 strTemp
		System.out.println(strTemp);
		//--==>> 사과,딸기,바나나

		// StringTokenizer 클래스 인스턴스 생성
		StringTokenizer st = new StringTokenizer(strTemp, ",");
		//-- strTemp 를 파싱 대상 문자열로, 『,』를 구분자로 생성자 호출



		// ○ StringTokenizer 클래스의 countTokens() 메소드
		//   : 파싱된 문자열(토큰)의 갯수를 리턴(반환)한다.
		strArr = new String[st.countTokens()];	// st.countTokens() = 3
		//-- 『strArr = new String[3];』와 동일한 구문



		// ★ 중요 (메소드 호출 순서와 cursor(헤드) 의 이동 여부 check~!)
		// ○ StringTokenizer 클래스의 hasMoreTokens() 메소드
		//  : 사용가능한 토큰이 있으면 true / 없으면 false 반환
		//    '있는지 없는지' 망만 봄. 실제 cursor(헤드) 의 이동은 없다.
        
		// ○ StringTokenizer 클래스의 nextToken() 메소드
		//  : 다음 토큰을 얻어온다. (cursor 이동 후 가리키는 토큰을 반환)
		//    구분자를 바꾸었을 경우 다음 호출에도 바뀐 구분자를 이용하여 토큰을 분리한다.
        
        
		n=0;
		while(st.hasMoreTokens())	// hasMoreTokens() : 망을 보고 true / false
		{
			strArr[n++] = st.nextToken();		// nextToken() : 버퍼 내 cursur 이동
		}


		System.out.println();
		System.out.print("파싱된 토큰(문자열) : ");

		for(String str : strArr)
			System.out.print(str + " ");	// "토큰_" 출력 ( _ 는 공백..)

		System.out.println();
		//--==>> 파싱된 토큰(문자열) : 사과 딸기 바나나

	}
}

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기