Java Fast IO 코드 템플릿
import java.io.*;
import java.util.StringTokenizer;
public class main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
while(st.hasMoreTokens()){
bw.write(Integer.parseInt(st.nextToken()) + " ");
}
//problem solve
bw.flush();
bw.close();
}
}
java로 알고리즘 문제를 풀 때
입력의 개수가 엄청 많은 경우 Scanner을 사용하면 시간이 오래 걸려서
알고리즘을 잘 구현했더라도 시간 초과로 틀릴 수 있다.
java에서는 이를 해결하기 위해
BufferedReader, BufferedWriter을 이용하여 입력과 출력을 더 빠르게 할 수 있다.
이 방법이 Scanner을 이용해 입출력하는 것보다 빠른 이유는 다음과 같다.
Scanner을 이용하여 입출력할 때는 바로바로 입출력을 해서 io가 빈번하게 발생하는데,
Buffered 방식을 이용하면 입출력을 즉시 하는 것이 아니라 Buffered에 저장했다가 필요할 때 io를 실시하기 때문에
보다 적은 io횟수로 입출력을 할 수 있어서 보다 빠르게 작업을 수행할 수 있다.
더불어 내가 해야할 일 중 입력은 엄청 많은데 출력이 적은 경우
입력만 BufferedReader로 받고 출력을 System.out.println으로 간편하게 해도 되지 않나 하는 의문이 들었다.
입력과 출력을 완전히 분리해서 사용하면 크게 문제가 되지 않는 것 같다.
예를 들어 입력은 모두 BufferedReader을 사용해서 받고
출력은 System.out.println으로만 하면 정상적으로 작동한다.
하지만 만약에 System.out.println 과 bw.write()를 하나의 프로그램에서 둘다 사용한다면
내가 예상한 코드대로 동작하지 않는 경우가 생긴다.
즉 입력을 받을 때도 한가지 메소드를 이용해야하고,
출력을 할 때도 한가지 메소드만 출력해서 이용해야 두가지 메소드가 서로 얽히지 않는다.
System.out.println, BufferedWriter.write 소요시간 비교
실제로 두 방법의 소요시간 차이를 측정해보았다.
환경은 인텔리제이에서 돌리고, 숫자 100만개를 출력하는 속도를 비교해보았다.
먼저 BufferedWriter을 이용한 코드이다.
import java.io.*;
import java.util.StringTokenizer;
public class main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//bw 사용
long start = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
bw.write(i + " ");
}
bw.flush();
long finish = System.currentTimeMillis();
long bwTime = finish - start;
bw.write("---------\n");
bw.write("Buffered write 소요 시간 "+ bwTime);
bw.close();
}
}
이번엔 System.out.println 을 이용한 코드이다
import java.io.*;
import java.util.StringTokenizer;
public class main {
public static void main(String[] args) throws IOException {
//bw 사용
long start = System.currentTimeMillis();
int count = 0;
for (int i=0; i<1000000; i++) {
System.out.print(i + " ");
}
long finish = System.currentTimeMillis();
long sysTime = finish - start;
System.out.println("---------\n");
System.out.println("System out 소요 시간 "+ sysTime);
}
}
같은 출력을 할 때
Buffered 방식을 이용하면 85ms,
System.out.print 방식을 이용하면 1171ms가 소요된 것을 알 수 있다.
입출력하는 데이터의 크기가 더 커질수록 두 방식의 시간차이는 더 커질 것이다.
반드시 Fastio로 문제를 풀어야 하는가?
하지만 꼭 모든 알고리즘 문제에 fastio를 적용해야하는 건 아니다.
입출력의 개수가 작은 편이라면
대부분 System 방식을 사용해서 간편하게 문제를 풀어도 해결할 수 있다.
이는 정확히 측정한 것이 아니고 문제마다 걸려있는 시간 제한에 따라 다르지만
내 개인적인 체감 상 데이터의 크기 N이 10,000개 이하정도라면
Buffered까지 사용하지 않고 System만을 이용해서도 문제를 해결할 수 있는 것 같다.
다만 Buffered를 이용해서 푼거에 비해 소요 시간이 많게 나올 수 있다.
알고리즘 문제를 푸는데 자바 입출력 속도를 위해 Buffered와 StringTokenizer 을 써서 코드를 여러줄 쓴다는 게
꽤 귀찮게 느껴지는 일이긴 하다.
상황에 따라 유동적으로 쓸 수 있도록 훈련하면 좋을 것 같다.
'Java' 카테고리의 다른 글
인텔리제이에서 vscode의 Ctrl + D (같은 단어 선택) 기능 단축키 찾기 (0) | 2022.06.30 |
---|---|
Eclipse 단축키가 안될 때 (자동 정렬 안될 때, 주석 안될 때) window (1) | 2022.04.11 |
추상 클래스의 상속, 추상 클래스 사용 이유 (0) | 2021.11.24 |