[공부 기록] Java 알고리즘 입출력 & 정렬 - Chapter 3.3 61p까지

날짜: 2025년 11월 27일
주제: Java I/O 성능 최적화 및 정렬 모델


책에서 새롭게 알게 된 내용 메모

1. 정렬의 비교 모델

  • 내용: 자바의 표준 라이브러리(Collections.sort)는 내부적으로 < (작다) 대신 <= (작거나 같다) 논리를 비교 모델로 사용한다.
  • 이유: 값이 같을 때 위치를 바꾸지 않는 안정 정렬(Stable Sort)을 보장하기 위함이다.

2. 입력: Scanner vs BufferedReader

결론: 실전(코딩 테스트)에서는 무조건 BufferedReader를 사용하는 것이 좋다.

성능 및 특징 비교

  • 속도:
    • Scanner: 느림 (입력 즉시 파싱)
    • BufferedReader: 매우 빠름 (약 5~10배 빠름)
  • 버퍼 크기:
    • Scanner: 1 KB (작음)
    • BufferedReader: 8 KB (큼)
  • 동작 방식:
    • Scanner: 문자를 하나씩 읽으며 정규식 검사 및 파싱 수행
    • BufferedReader: '바구니(Buffer)'에 문자를 가득 찰 때까지 쌓아뒀다가 한 번에 읽음
  • 데이터 타입:
    • Scanner: nextInt() 등으로 자동 변환 지원
    • BufferedReader: 오직 String 데이터만 가짐 (형변환 필수)
  • 예외 처리:
    • Scanner: 불필요
    • BufferedReader: IOException 필수 (throws 처리)

왜 BufferedReader가 더 빠를까?

CPU와 입출력 장치 사이의 통신 횟수를 줄이는 것이 핵심이다. 물건을 하나씩 낱개로 나르는 것(Scanner)보다, 트럭에 꽉 채워서 한 번에 나르는 것(BufferedReader)이 훨씬 효율적인 원리와 같다.


3. 문자열 분리: split() vs StringTokenizer

한 줄의 문자열을 공백 단위로 나눌 때도 성능 차이가 발생한다.

  • String.split(" "): 정규식(Regex)을 기반으로 동작하므로 내부 연산 비용이 커서 느리다.
  • StringTokenizer: 단순히 공백 문자만 찾아 잘라내므로 빠르다.

Tip: 데이터 양이 적다면 split이 편하지만, 10만 개 이상의 데이터라면 StringTokenizer를 쓰자.


4. 출력: System.out.println vs StringBuilder

입력만큼 출력 속도도 중요하다. 반복문 안에서 출력을 계속 호출하면 시간 초과(TLE)의 원인이 된다.

피해야 할 패턴 (Bad)

for(int i=0; i<100000; i++) {
    System.out.println(i); // 매번 콘솔에 접근하므로 오버헤드가 매우 큼
}

권장패턴

StringBuilder sb = new StringBuilder();
for(int i=0; i<100000; i++) {
    sb.append(i).append("\n"); // 문자열을 모아둠 (빠름)
}
System.out.println(sb); // 딱 한 번만 출력

0개의 댓글