거북이-https://velog.io/@violet_evgadn 이전완료

StringBuilder 본문

코딩 테스트 시 알면 좋은 것들

StringBuilder

VioletEvgadn 2023. 1. 15. 23:32

코딩 테스트 시 필요한 이유

이전에도 말했듯 코딩 테스트에서 나올 확률이 가장 높은 문제는 "문자열 처리" 문제이다.

진짜 문제를 풀다보면 생각 그 이상으로 문자열 처리 문제를 많이 낸다.

 

문자열 처리에선 split같은 String 고유 함수도 중요하겠지만 StringBuilder 객체가 매우 중요하다고 말할 수 있다.

이유는 많지만 중요한 이유는 2가지라고 생각한다.

 

먼저 연산 속도의 문제이다.

일반적으로 String 문자열을 합칠 때 "String + String" 형식으로 "+" 연산자를 활용한다.

하지만 "+" 연산자를 통해 String 문자열을 합치면 성능도 떨어지고 메모리도 비효율적으로 활용된다.

(이유는 아래에서 자세히 알아보자)

 

2번째 문제는 String 객체의 경우 Index에 해당하는 문자를 삭제하거나 변경하는 것이 어렵고 String 중간에 있는 문자열 또한 삭제 혹은 변경이 어렵다.

String 객체에서 이런 처리가 어려운 이유는 간단한데, String이 "불변 객체"이기 때문에 생기는 문제이다.

String 객체는 불변 객체이기 때문에 애초에 문자열 일부를 삭제하거나 변경시키는 것을 상정하지 않았다. 중간 문자열이 바뀌는 순간 그 즉시 해당 객체는 다른 메모리 공간에 선언되어 새로운 String 객체로 취급될 것이므로 메서드를 실행시킨 String 객체 값은 바뀌지 않기 때문에 만들 필요가 없는 것이다.

 

참고로 StringBuilder와 비슷한 StringBuffer라는 것이 존재하는데 StringBuffer는 "Thread Safe"한 객체이며 StringBuilder는 아니다.

하지만 이전에 말했듯 "Thread Safe"한 객체는 조금 더 많은 자원을 사용하고 코딩 테스트에선 "Thread Safe"를 고려하지 않아도 되기 때문에 StringBuilder를 사용하면 된다.

Thread를 공유하거나 비동기 작업이 필요할 경우에만 StringBuffer를 사용하는 것이 좋다.

 

이런 문제들을 처리할 수 있는 메서드들이 모두 StringBuilder에는 존재한다.

따라서 String 문제를 제대로 처리하기 위해선 꼭 StringBuilder를 공부해야한다 생각해서 이번 Section에 정리했다.


+ 연산자를 통한 문자열 합치기를 지양해야 하는 이유

그렇다면 왜 String 객체를 "+" 연산자로 합치는 것을 지양해야할까?

 

Java에서는 "+" 연산자를 통해 String 객체를 합칠 경우 아래와 같은 단계를 거친다.

  1. StringBuilder 클래스를 만든다
  2. StringBuilder.append()를 통해 문자열 2개를 StringBuilder에 합친다.
  3. StringBuilder.toString()을 통해 합쳐진 문자열을 반환한다.

즉, "+" 연산자로 String 객체를 1번 합칠 때마다 StringBuilder 클래스의 생성 및 삭제가 일어나는 것이다.

 

물론 "+" 연산자로 String 객체를 1번만 합친다는 것이 확정되어 있다면 StringBuilder로 처리하는 것보다 깔끔하고 큰 성능차이도 나지 않을 것이다.

하지만 String 객체에 문자열을 계속해서 붙이는 경우 "+" 연산자가 수행될 때마다 StringBuilder 클래스의 생성 및 삭제가 될 것이므로 성능이 떨어지며 메모리 또한 비효율적으로 활용된다.

 

추가로 문자열을 합치는 String 고유 함수 "String.concat" 메서드도 살펴보자.

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}

 

위 메서드에서 유심히 봐야 하는 것은 char[] buf 선언 부분이다.

String.concat은 char[] buf라는 새로운 공간을 선언한 뒤 선언된 공간에 기존 문자열을 먼저 buf에 입력한다.

그리고 Parameter로써 들어온 String str을 char[] buf의 남은 공간에 채워주는 형식으로 실행된다.

 

결국 String.concat 메서드도 char[] buf라는 합친 문자열을 저장할 새로운 공간을 선언해주는 과정이 필요하다.

또한 문자열을 합친 이후 "new String"문구를 통해 String 문자열을 새로 선언해주는 과정도 추가된다.

 

StringBuilder는 ArrayList와 같이 배열 크기를 먼저 잡고 필요할 때마다 확장하는 방식이므로 당연히 계속해서 객체 선언이 필요한 concat보다 빠르다고 할 수 있겠다.


StringBuilder

◎ String to StringBuilder

StringBuilder sb = new StringBuilder(String s);

 

◎ StringBuilder to String

아래 모든 상황에서 StringBuilder 객체를 "sb"로 선언했다고 가정하겠다.

String str = sb.toString();

 

◎ 문자열 뒤에 붙이기

// 문자 1개를 붙임
sb.appned(char c);

// 문자열을 붙임
// String도 CharSequence Interface를 상속받은 객체라는 것을 기억하자.
sb.append(CharSequence s);

// 'start ~ end-1' 구간의 부분 문자열을 붙임
sb.append(CharSequence s, int start, int end);

이외에도 sb.append()를 통해 Object나 char[] 배열 값을 넣을 수도 있다.

하지만 이렇게 사용하는 경우는 많이 존재하지 않으므로 위 3개 사용 방법만 잘 알아둬도 될 것이다.

 

◎ Index 문자 반환

// Index번째 문자를 반환
char c = sb.charAt(int index);

 

◎ 중간 문자열 삭제

// 문자열 중 "start ~ end-1" Index에 위치한 문자들을 지움
sb.delete(int start, int end);

 

◎ 중간 문자 삭제

// index에 존재하는 문자 삭제
sb.deleteCharAt(int index);

 

◎ 일치하는 문자열 Index 찾기

// str이 위치한 "첫번째 Index" 반환
// 포함되지 않았을 경우 -1 반환
sb.indexOf(String str);

// fromIndex 위치부터 str이 포함되었는지 검색
// 포함되지 않았을 경우 -1
sb.indexOf(String str, int fromIndex);

// str이 위치한 "마지막 Index" 반환
// 포함되지 않았을 경우 -1 반환
sb.lastIndexOf(String str);

// fromIndex 위치부터의 문자열 중 마지막으로 str이 포함된 Index 반환
// 포함되지 않았을 경우 -1 반환
sb.lastIndexOf(String str, int fromIndex);

 

◎ 중간에 문자열 추가하기

// offset 위치에 str을 추가시킴
sb.insert(int offset, String str);

insert 또한 append 메서드처럼 String 대신 CharSequence, char[], Object 등 많은 객체가 들어갈 수 있다.

자세히 확인해보고 싶으면 아래 사이트를 참조하자.

https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html#append(java.lang.CharSequence,%20int,%20int) 

 

StringBuilder (Java Platform SE 7 )

Inserts the string into this character sequence. The characters of the String argument are inserted, in order, into this sequence at the indicated offset, moving up any characters originally above that position and increasing the length of this sequence by

docs.oracle.com

 

◎ 문자열 대체하기

sb.replace(int start, int end, String str);

 

◎ 문자열 뒤집기

sb.reverse();

 

◎ 부분 문자열 추출

// "start ~ end-1"에 존재하는 부분 문자열 반환
sb.substring(int start, int end);

// "start ~ 문자열 끝"에 존재하는 부분 문자열 반환
sb.substring(int start);

'코딩 테스트 시 알면 좋은 것들' 카테고리의 다른 글

Trie  (0) 2023.02.01
Collections Method  (0) 2023.01.15
Char 배열 처리  (0) 2023.01.09
조합과 순열  (0) 2023.01.03
문자열 뒤집기  (0) 2023.01.03
Comments