[Java] StringBuilder, BufferedReader, BufferedWriter

thezz9·2025년 3월 14일
1

코딩테스트에 도움되는 StringBuilder, BufferedReader, BufferedWriter에 대해 알아보자.
특히 높은 레벨의 코딩테스트에서는 실행시간이나 메모리 사용량 등의 제약조건이 있기때문에 익혀두면 좋다.
내가 느끼기엔 낮은 레벨의 문제에서도 성능을 신경 쓰면 점수도 조금 더 주는 것 같다. (착각일지도 모름 ㅎ.ㅎ)


1. String vs StringBuilder

String (불변 객체)

String 객체는 불변(immutable)이기 때문에 한 번 생성된 문자열은 바꿀 수 없다. 즉, 문자열을 수정할 때마다 새로운 String 객체가 만들어지므로 메모리를 많이 차지하고 속도도 느려질 수 있다.

String str = "Hello";
str += " World";
str += "!";
System.out.println(str);

위 코드에서 str이 변하는 것처럼 보이지만, 실제로는 "Hello", "Hello World", "Hello World!" 세 개의 String 객체가 메모리에 존재하게 되어 비효율적이다.
기존 문자열은 GC(가비지 컬렉션)에 의해 나중에 정리된다.

StringBuilder (가변 객체)

반면, StringBuilder는 내부 버퍼를 사용하여 기존 문자열을 직접 수정하므로 속도가 훨씬 빠르다.

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
sb.append("!");
System.out.println(sb.toString());

여기서 새로운 객체를 생성하는 것이 아니라, 기존의 StringBuilder 내부 버퍼를 수정하므로 String보다 성능이 우수하다.

💡 언제 StringBuilder를 사용할까?

  • 문자열을 반복적으로 수정해야 할 때 (append, insert, replace 등)
  • 반복문에서 문자열을 이어붙일 때 (for, while에서 += 대신 사용)
  • StringBuffer보다 빠른 연산이 필요하고, 멀티스레드 환경이 아닐 때

(⭐+추가) StringBuffer vs StringBuilder

StringStringBufferStringBuilder
속성불변(Immutable)가변(Mutable)가변(Mutable)
성능느림중간 (멀티스레드 안전)가장 빠름 (단일 스레드)
스레드 안전성✔️ (멀티스레드 지원)
동기화불필요있음없음

StringBufferStringBuilder와 거의 비슷한 역할을 한다. String처럼 불변이 아니라 기존 문자열을 수정하는 방식이라서 String보다 빠른 성능이라는 것은 동일하다.

차이점은 StringBuffersynchronized(동기화)가 되어 있고, StringBuilder는 그렇지 않다는 점이다.

즉, StringBuilder는 성능이 더 빠르기때문에 싱글 스레드에서 사용하는 게 좋고, StringBuffer는 멀티스레드 환경에서 데이터가 꼬이지 않도록 동기화가 필요할 때 사용하는 게 좋다.


2. Scanner vs BufferedReader

코딩 테스트에서는 입력 속도도 중요한 요소다.
문제를 풀다 보면 입력 속도가 성능에 큰 영향을 미치는 경우가 많다.

Scanner (편리한 입력)

Scanner는 다양한 데이터 타입을 쉽게 읽을 수 있고, 정규 표현식까지 활용할 수 있어 편리하다

Scanner sc = new Scanner(System.in);
int num = sc.nextInt(); // 정수 입력
String str = sc.next(); // 문자열 입력
sc.close();

그러나, Scanner는 내부적으로 입력을 한 글자씩 읽고 변환하는 과정이 많아서 속도가 느리다.

BufferedReader (빠른 입력)

대량의 입력을 처리할 때는 BufferedReader를 사용하면 속도가 훨씬 빠르다.

보통 System.in과 함께 사용하려면 InputStreamReader와 함께 사용한다.

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine(); // 한 줄 입력
int num = Integer.parseInt(br.readLine()); // 문자열 → 숫자로 변환
br.close();

BufferedReader는 입력을 한 번에 버퍼에 저장한 후 처리하므로 Scanner보다 빠르다.
다만, 숫자 입력을 받으려면 Integer.parseInt(br.readLine())처럼 명시적으로 변환해야 하는 번거로움이 있다.

💡 언제 Scanner를 사용할까?

  • 코드가 간결해야 할 때
  • 다양한 데이터 타입(int, double, String)을 쉽게 처리할 때

💡 언제 BufferedReader를 사용할까?

  • 입력 속도가 중요한 경우 (예: 알고리즘 문제 풀이)
  • 대량의 데이터를 빠르게 읽어야 할 때

3. System.out.println() vs BufferedWriter

출력도 입력과 마찬가지로 성능 차이가 난다.

System.out.println() (편리한 출력)

System.out.println("Hello, World!");
System.out.println(100);
System.out.println(3.14);

이렇게 간단한 코드에선 문제가 없지만, 반복문에서 자주 사용하면 비효율적이다.
이유는 매번 System.out에 데이터를 직접 보내기 때문이다.

BufferedWriter (빠른 출력)

BufferedWriter는 데이터를 버퍼에 모아서 한 번에 출력하므로 성능이 향상된다.

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("Hello, World!\n");
bw.write("BufferedWriter는 빠르다.\n");
bw.flush(); // 출력 후 반드시 flush() 필요
bw.close(); // 자원 해제

버퍼를 이용하면 여러 번 write()를 호출해도 실제 I/O 연산을 줄여서 성능을 개선할 수 있다.

💡 언제 System.out.println()을 사용할까?

  • 단순한 출력이 필요할 때
  • 속도가 중요하지 않은 경우

💡 언제 BufferedWriter를 사용할까?

  • 출력 속도가 중요한 경우 (예: 알고리즘 문제 풀이)
  • 많은 데이터를 한 번에 출력해야 할 때
  • 파일을 다룰 때 (BufferedWriterFileWriter와 함께 쓰면 더욱 효율적)

성능 비교

기능StringStringBuilderBufferedReaderScannerBufferedWriterSystem.out.println()
가변성불변가변----
속도느림빠름빠름느림빠름느림
멀티스레드 지원✔️❌ (StringBuffer 사용 시 ✔️)----
입출력 최적화--✔️✔️
사용 예시문자열 변경 없음문자열 반복 수정빠른 입력 필요간단한 입력빠른 출력 필요간단한 출력

정리

1. 문자열 다루기

  • 변경이 많다면 StringBuilderString보다 성능이 좋음.

2. 입력 속도 비교

  • BufferedReaderScanner보다 빠름.
  • Scanner는 간편하지만 속도가 느림.

3. 출력 속도 비교

  • BufferedWriterSystem.out.println()보다 빠름.
  • 출력이 많다면 BufferedWriter를 쓰고, 적다면 System.out.println()을 사용.

코딩 테스트에서 입출력 속도는 중요하다.
원시적인 풀이 방법에서 벗어나서 이것들을 사용하는 습관을 들여야겠다.

profile
개발 취준생

0개의 댓글