코딩테스트에서 입출력은 단순히 “값 읽고 출력하는 코드”가 아니라,
시간 복잡도와 함께 성능을 결정하는 핵심 요소다.
특히 백준 이나 SW Expert Academy 같은 환경에서는 입력 데이터가 수십만~수백만 개가 되는 경우가 많아서,
입출력을 잘못 사용하면 알고리즘은 맞아도 시간 초과가 발생한다.
그래서 코딩테스트에서는 보통 다음 4개를 가장 많이 사용한다.
- BufferedReader
- StringTokenizer
- StringBuilder
- BufferedWriter
그리고 추가적으로:
- Scanner
- System.out.println
- split()
- InputStream
- 빠른 입력(Fast I/O)
까지 이어서 공부하게 된다.
1. 코딩테스트에서 입출력이 중요한 이유
예를 들어 숫자 100만 개를 입력받는다고 해보자.
Scanner sc = new Scanner(System.in);
를 사용하면 내부적으로 정규식 처리와 타입 파싱이 반복되기 때문에 느리다.
반면:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
는 버퍼를 사용해서 한 번에 많은 데이터를 읽어오기 때문에 훨씬 빠르다.
즉:
방식 속도
| Scanner | 느림 |
| BufferedReader | 빠름 |
코딩테스트에서는 대부분 BufferedReader를 사용한다고 보면 된다.
2. BufferedReader
2-1. BufferedReader란?
입력을 빠르게 받기 위한 클래스다.
데이터를 한 글자씩 읽는 것이 아니라:
“버퍼(Buffer)”라는 임시 저장 공간에 한 번에 읽어놓고 사용한다.
그래서 속도가 빠르다.
2-2. 기본 사용법
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
이 코드가 처음 보면 굉장히 어렵다.
하나씩 분해해보자.
2-3. InputStreamReader란?
System.in은 바이트(byte) 기반 입력이다.
하지만 우리는 문자열(String)을 사용하고 싶다.
그래서:
new InputStreamReader(System.in)
를 통해:
바이트 입력 -> 문자 입력
으로 변환한다.
2-4. BufferedReader는 왜 붙일까?
InputStreamReader만 사용하면 속도가 충분히 빠르지 않다.
그래서:
new BufferedReader(...)
로 감싸서 버퍼 기능을 추가한다.
최종 구조:
System.in
↓
InputStreamReader
↓
BufferedReader
3. readLine()
BufferedReader에서 가장 중요한 메서드다.
String s = br.readLine();
한 줄 전체를 문자열로 읽는다.
예시 입력:
10 20
이면:
String s = br.readLine();
결과:
s = "10 20"
4. 왜 StringTokenizer가 필요한가?
readLine()은 한 줄 전체를 문자열로 읽는다.
즉:
10 20
을 읽으면:
"10 20"
이라는 문자열 하나가 된다.
하지만 우리는:
10
20
으로 나눠서 사용하고 싶다.
그래서 사용하는 것이:
StringTokenizer
이다.
5. StringTokenizer
5-1. 역할
문자열을 특정 기준으로 잘라준다.
보통 공백 기준으로 분리한다.
5-2. 기본 사용법
StringTokenizer st =
new StringTokenizer(br.readLine());
예를 들어 입력:
10 20 30
이면:
st.nextToken()
을 호출할 때마다:
10
20
30
순서대로 꺼낼 수 있다.
6. nextToken()
st.nextToken();
다음 토큰(문자열 조각)을 반환한다.
예제
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st =
new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
System.out.println(a + b);
입력:
3 5
동작 과정:
readLine() -> "3 5"
StringTokenizer:
["3", "5"]
nextToken() -> "3"
nextToken() -> "5"
결과:
8
7. Integer.parseInt()
중요하다.
nextToken()은 문자열(String)을 반환한다.
즉:
"10"
이다.
우리는 숫자로 사용해야 하므로:
Integer.parseInt()
로 정수 변환을 해야 한다.
8. StringTokenizer vs split()
많은 사람들이 처음에는 split()을 사용한다.
String[] arr = br.readLine().split(" ");
가능은 하다.
하지만 코딩테스트에서는 보통:
StringTokenizer
를 더 많이 사용한다.
이유는 성능 때문이다.
split()이 느린 이유
split()은 내부적으로 정규식(regex)을 사용한다.
정규식은 강력하지만 느리다.
대량 입력에서는 시간 차이가 꽤 발생한다.
비교
방식 속도
| split() | 느림 |
| StringTokenizer | 빠름 |
그래서 코딩테스트에서는:
BufferedReader + StringTokenizer
조합이 사실상 표준이다.
9. 출력은 왜 StringBuilder를 사용할까?
많은 사람들이 처음에는:
System.out.println();
를 반복한다.
예:
for(int i = 0; i < 100000; i++) {
System.out.println(i);
}
하지만 출력도 매우 느릴 수 있다.
10. StringBuilder
역할
문자열을 효율적으로 이어붙이는 클래스.
왜 필요한가?
Java 문자열(String)은 immutable(불변)이다.
즉:
s += "a";
를 할 때마다 새로운 문자열 객체가 생성된다.
반복하면 매우 비효율적이다.
11. StringBuilder 기본 사용법
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println(sb);
결과:
Hello World
12. 코딩테스트에서의 핵심 패턴
StringBuilder sb = new StringBuilder();
for(int i = 0; i < N; i++) {
sb.append(i).append('\n');
}
System.out.print(sb);
핵심은:
출력을 모아뒀다가 한 번에 출력
하는 것이다.
13. BufferedWriter
사실 출력 최적화용 클래스도 있다.
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(System.out));
하지만 실제 코딩테스트에서는:
StringBuilder + System.out.print()
조합을 훨씬 많이 사용한다.
14. BufferedWriter 기본 사용법
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("Hello\n");
bw.write("World\n");
bw.flush();
bw.close();
15. flush()란?
버퍼에 모아둔 데이터를 실제로 출력한다.
버퍼 출력 흐름:
write()
↓
버퍼에 저장
↓
flush()
↓
실제 출력
16. close()란?
스트림을 닫는다.
보통:
flush();
close();
순서로 사용한다.
17. StringBuilder vs BufferedWriter
실무에서는 둘 다 쓰지만
코딩테스트에서는 보통:
StringBuilder
가 더 편하다.
이유:
- 문법 간단
- 예외 처리 덜 복잡
- 문자열 조작 편함
18. 코딩테스트 표준 템플릿
가장 많이 사용하는 형태
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int N = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
sb.append(a + b).append('\n');
}
System.out.print(sb);
}
}
이 템플릿은 진짜 엄청 많이 사용한다.
19. throws Exception을 쓰는 이유
원래는 예외 처리를 해야 한다.
try-catch
하지만 코딩테스트에서는 코드 길이를 줄이기 위해:
throws Exception
를 많이 사용한다.
20. 자주 나오는 입력 패턴들
20-1. 한 줄에 숫자 여러 개
입력:
1 2 3
코드:
StringTokenizer st =
new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
20-2. 배열 입력
입력:
1 2 3 4 5
코드:
int[] arr = new int[N];
StringTokenizer st =
new StringTokenizer(br.readLine());
for(int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
20-3. 문자열 입력
String s = br.readLine();
20-4. 문자 하나씩 처리
char[] ch = br.readLine().toCharArray();
'BackEnd > Java' 카테고리의 다른 글
| java 대소문자 바꾸는 법 (0) | 2026.02.03 |
|---|---|
| 생성자, toString 그리고 getter&setter (1) | 2025.08.08 |