Java로 코딩을 할 때, 특히 많은 양의 데이터를 출력해야 하는 상황에서 System.out.println()을 사용하는 것은 실행 시간에 큰 영향을 미칠 수 있다.
이를 해결하기 위해 BufferedWriter를 사용하여 성능을 크게 향상시킬 수 있었습니다. 이번에는 System.out.println()을 BufferedWriter로 대체하는 과정과 그 효과에 대해 자세히 설명드리겠습니다.
System.out.println()
아래 코드는 System.out.println()을 사용하여 RGB 값의 모든 조합을 출력하는 구조이다. for 문을 세 번 중첩하여 모든 경우의 수를 계산하고, 각 경우에 System.out.println()으로 출력했습니다. 코드의 실행 시간은 무려 3995ms나 소요되었다.
import java.io.*;
public class Codeup1084 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String array[] = br.readLine().split(" ");
int r = Integer.parseInt(array[0]);
int g = Integer.parseInt(array[1]);
int b = Integer.parseInt(array[2]);
int cnt = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < g; j++) {
for (int k = 0; k < b; k++) {
System.out.println(String.format("%d %d %d", i, j, k));
cnt++;
}
}
}
System.out.print(cnt);
}
}
ps. 해당 문제는 코드업 1084번의 문제를 예시로 가져왔습니다.
System.out.println()을 사용할 때, 매 출력마다 버퍼에 쌓이지 않고 바로 출력되기 때문에 시간이 오래 걸렸다.
BufferedWriter로 성능 개선하기
BufferedWriter는 출력할 내용을 메모리에 버퍼로 쌓아두었다가 한 번에 출력하는 방식이다.
많은 데이터를 출력할 때 유리하며, 실행 시간을 크게 줄일 수 있다. 이때 BufferedWriter는 java.io.* 패키지를 import해야 하며, 예외 처리가 필요합니다.
import java.io.*;
public class Codeup1084 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String array[] = br.readLine().split(" ");
int r = Integer.valueOf(array[0]);
int g = Integer.valueOf(array[1]);
int b = Integer.valueOf(array[2]);
int cnt = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < g; j++) {
for (int k = 0; k < b; k++) {
bw.write(i + " " + j + " " + k + "\n");
cnt++;
}
}
}
bw.write(String.valueOf(cnt));
bw.flush();
}
}
결과와 성능 차이
위의 코드에서는 System.out.println() 대신 BufferedWriter의 write() 메서드를 사용했다. 또한 개행을 위해 \n을 추가해 주었고, 모든 데이터가 버퍼에 쌓인 후 마지막에 flush()로 한 번에 출력하고, 이로 인해 실행 시간은 351ms로 줄어들며, 약 9배의 성능 향상이 이뤘다.
주의 사항
- BufferedWriter는 println()처럼 자동 개행 기능이 없으므로, 개행이 필요할 때는 \n이나 newLine() 메서드를 사용
- 또한 버퍼를 사용한 코드이기 때문에, 출력이 끝난 후 반드시 flush()나 close()로 버퍼의 내용을 출력해줘야 데이터 손실을 방지
결론
많은 양의 데이터를 출력해야 하는 상황에서는 BufferedWriter를 사용하는 것이 효과적이다. 기존의 System.out.println()보다 훨씬 빠른 속도로 출력을 처리할 수 있어, 시간 제한이 엄격한 환경에서 큰 도움이 된다.