StringBuilder/Buffer/Tokenizer

TIL·2022년 12월 20일
0

Java (최은빈)

목록 보기
19/27

StringBuilder / StringBuffer 성능비교

  1. String.concat
  • 쓰지마
  1. "" + ""
  • 기존 "foo", "bar" 와 다른 주소에 "foobar" 할당 (string pool)
  • 메모리 할당하는 속도 더해짐
  1. StringBuilder
  • Heap에 저장
  • 단일 스레드 환경에서 주로 사용. 동기화 지원X (코테 문제 풀기)
  1. StringBuffer
  • 동기화(여러개의 스레드(사용자)에 대해 순서화) 지원하기 때문에 Builder 보다 느림
  • 멀티 스레드 (웹개발) 환경에서 주로 사용



StringBuilder

package me.day08.stringbuilder;

import java.util.Arrays;

public class StringBuilderExample {
    public static void main(String[] args) {
        // StringBuilder implements CharSequence

        // append(), insert()
        StringBuilder stringBuilder1 = new StringBuilder("Java"); // string pool 아닌 heap
        stringBuilder1.append(" is OOP Language");
        stringBuilder1.insert(0, "The ");
        System.out.println(stringBuilder1); // The Java is OOP Language

        // setLength(), replace()
        stringBuilder1.setLength(11);
        System.out.println(stringBuilder1); // The Java is

        stringBuilder1.replace(4, 4 + "java".length(), "c++");
        System.out.println(stringBuilder1); // The c++ is

        // capacity(), trimgToSize(), delete()
        System.out.println(stringBuilder1.capacity()); // 42 (데이터보다 크게 만들어짐. 부족해지면 더블링으로 공간 계속 만듦)
        stringBuilder1.trimToSize();
        System.out.println(stringBuilder1.capacity()); // 10 (실제 할당한 데이터의 사이즈)

        stringBuilder1.delete(0, 3); // 3 전까지
        System.out.println(stringBuilder1); // c++ is
        System.out.println();

        // toString() : StringBuilder(heap) -> String(string pool) (수정 불가)
        String string = stringBuilder1.toString();
        System.out.println(string); // c++ is
        System.out.println();

        // compareTo()
        StringBuilder stringBuilder2 = new StringBuilder(string.strip());
        System.out.println("CompareTo = " + stringBuilder2.compareTo(stringBuilder1)); // 67 // 사전식 비교
        System.out.printf("%d\n", (int)' ');
        System.out.printf("%d\n", (int)'c');

        // indexOf(), lastIndexOf()
        System.out.println("indexOf = " + stringBuilder2.indexOf("is"));
        System.out.println("lastIndexOf = " + stringBuilder2.lastIndexOf("is"));
        System.out.println();

        // subSequence() == subString()
        CharSequence charSequence = stringBuilder2.subSequence(1, 2); // 2 전까지
        System.out.println("SubString = " + charSequence);
        System.out.println();

        // getChars()
        char[] chars = new char[100]; // 문자 배열 new 하면 '\0'( == 영문자 != 0) 로 초기화 (null 은 영문자를 객체화 시킨것)
        stringBuilder2.getChars(1, 5, chars, 2); // '++ i'를 chars에 넣기 (2번째 인덱스 부터)
        System.out.println(Arrays.toString(chars));
        for (int i = 0; i < chars.length; i++) {
            System.out.printf("%c = %d\n", chars[i], (int)chars[i]); // 문자의 아스키코드 값
        }
        System.out.println();

        // reverse()
        StringBuilder stringBuilder3 = stringBuilder2.reverse(); // 새로운 공간에 넣음
        System.out.println("Reverse = " + stringBuilder3); // si ++c
        System.out.println("stringBuilder2 = " + stringBuilder2); // 기존 공간 수정o
    }
}



StringBuffer

  • 메소드는 전부 동일
  • 동기화 지원하는 것만 다름



StringTokenizer

  • 쪼개진 문자열 : token
    구분자 : delimiter
  • 생성자
  1. public StringTokenizer(String str);
    • 절달된 매개변수 str을 기본 delim 으로 분리
    • 기본 delimiter: " \t\n\r\t" (공백문자)
  2. public StringTokenizer(String str, String delim);
    • 특정 delim으로 문자열 분리
  3. public StringTokenizer(String str, String delim, boolean returnDelims);
    • str을 특정 delim으로 분리시키는데 그 delim까지 token으로 포함할지를 결정
    • 매개변수가 returnDelims로 true 포함, false일땐 포함하지 않음
package me.day08.stringtokenzier;

import java.util.Iterator;
import java.util.StringTokenizer;

public class StringTokenizerExample {
    public static void main(String[] args) {
        final String str = "홍홍, 박박, 김김";

        // split() : 공백문자 포함하여 반환
        String[] splitString = str.split(", ");
        for (String s: splitString) {
            System.out.println("s = " + s);
        }
        System.out.println();

        // StringTokenizer : 공백문자 삭제하여 반환
        // countTokens() : 토큰(짤린 문자열)의 개수
        StringTokenizer stringTokenizer1 = new StringTokenizer(str, ", ");
        int count = stringTokenizer1.countTokens();
        System.out.println("count = " + count);
        System.out.println();

        // count 알때 nextToken() 으로 가져오기 (무조건 String 으로만 반환 가능 != nextElement())
        for (int i = 0; i < count; i++) {
            String token = stringTokenizer1.nextToken();
            System.out.println("token = " + token);
        }
        System.out.println();

        // count 모를때 hasMoreTokens(), nextToken() 으로 가져오기
        // StringTokenizer는 내부적으로 어떤 위치의 토큰을 사용하였는지 기억함 그 위치를 다음으로 옮김
        StringTokenizer stringTokenizer2 = new StringTokenizer(str, ", ");
        while (stringTokenizer2.hasMoreTokens()) { // 또 자를 토큰 있으면
            String token = stringTokenizer2.nextToken();

            // 전달할 토큰이 object 이면 nextElement()
            Object token2 = stringTokenizer2.nextElement();
            Integer token3 = (Integer) token2; // Object는 최상위 클래스 이므로 자른 데이터를 다른 래퍼 클래스(원시타입을 매핑한 클래스) 데이터로 바꿀 수 있음
            // Integer.parseInt() 로 함수 부르는 것보다 바로 타입 캐스팅 하는 것이 좋음
            // throws NumberFormatException 하므로 trt catch 로 또 잡아줘야함

            System.out.println("token = " + token);
            System.out.println("token2 = " + token2);
            System.out.println("token3 = " + token3);
        }
        System.out.println();

        // hasMoreToken() 아닌 Iterator 로 돌리기 (Collection)
        // index 가 명확하지 않아 직접 indexing 해야 하는 경우, Iterator로 반복문 가능
        StringTokenizer stringTokenizer3 = new StringTokenizer(str, ", ");
        Iterator<Object> iterator = stringTokenizer3.asIterator();
        while (iterator.hasNext()) {
            Object token = iterator.next();
            System.out.println("token = " + token);
        }
        System.out.println();


        // StringTokenizer vs String split()
        // String split() - 빈 문자열도 토큰으로 인식, 정규식 사용 가능, 잘라낸 결과를 배열에 담아서 반환 (데이터 양이 많은 경우 성능 떨어짐)
        // StringTokenizer - 빈 문자열은 토큰으로 인식하지 않음

        String data = "100,,,200,300";
        String[] strings = data.split(",");
        for (int i = 0; i < strings.length; i++) {
            System.out.println("strings[i] = " + strings[i]); // 공백도 나옴
        }
        System.out.println("strings.length = " + strings.length);
        System.out.println();

        StringTokenizer stringTokenizer = new StringTokenizer(data, ","); // regex 불가능
        System.out.println("stringTokenizer.countTokens() = " + stringTokenizer.countTokens()); // 자르기 전에는 토큰 수 정확히 나옴
        while (stringTokenizer.hasMoreTokens()) {
            System.out.println("stringTokenizer.nextToken() = " + stringTokenizer.nextToken()); // 공백 안나옴
        }
        System.out.println("stringTokenizer.countTokens() = " + stringTokenizer.countTokens()); // 자른 후에는 0 개 => 포인터가 끝까지 갔기 때문 (자를게 없다)

    }
}

  • String split()
    • 빈 문자열도 토큰으로 인식 (중간을 기준으로 양 옆을 자르므로)
    • 정규식 사용 가능
    • 잘라낸 결과를 배열에 담아 반환 (데이터 양이 많은 경우 성능 떨어짐)
  • StringTokenizer()
    • 자르는 순간마다 String 으로 반환시켜 성능 더 좋다. -> 코테에서 더 유리.
    • split() 후 모든 공백문자 삭제하여 반환 (빈 문자열은 토큰으로 인식하지 않음)
  • object
    • 제일 최상위의 클래스여서 String 뿐만 아니라 다른 데이터 타입도 들어 올 수 있다.
    • 즉, 자른 데이터를 다른 데이터 타입 (Integer, Double, ..) 으로 전달 할 수 있다. (원시타입을 매핑 시킨 Wrapper 클래스)
    • Integer.parseInt() 로 함수 부르는 것보다 바로 타입 캐스팅 하는 것이 좋다.
      throws NumberFormatException 하므로 trt ~ catch 로 또 잡아줘야함

0개의 댓글

관련 채용 정보