1. 문제
◽ 주소 : https://www.acmicpc.net/problem/2588
◽ 문제 내용 :
2. 풀이
◽ 풀이 1 : java.util.Scanner, System.out.println(); 사용
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
int n = kb.nextInt();
int m = kb.nextInt();
System.out.println(n * (m % 10));
System.out.println(n * (m % 100/10));
System.out.println(n * (m / 100));
System.out.println(n * m);
kb.close();
}
}
- Scanner와 System.out.print()는 자바 배울때 제일 먼저 배우고 가장 흔하게 사용하는 방법이다.
- 하지만 둘 다 속도면에서 매우 느린편에 속한다. 왜냐하면 리소스를 많이 사용하여 성능 부하를 초래하기 때문이다.
- 입출력이 많은 코드에서는 지양하는 것이 좋다.
- Scanner의 경우 최적화 관점에서 명시적으로 close()를 선언하여 닫아주는것이 좋다.
- 자바에는 Garbage Collector/Collection에 의해서 내부 객체및 리소스들이 자동으로 정리되기 때문에, close() 콜하지 않아도 크게 문제되진 않지만 Garbage Collector가 실행이 완료될 때까지 스캐너에 할당된 리소스들이 그대로 유지되기 때문에 최적화 관점에서는 close()를 통해 스트림을 종료해주는 것이 좋다.
- 하지만, 주의해야할 점은 close()를 통해 닫게 된다면 프로그램 상에서 다시는 Scanner를 사용할 수 없으니 유의해야한다.
- 순서대로 m의 일의 자리, 십의 자리, 백의 자리를 구해야하는게 문제의 핵심이다.
- m의 일의 자리는 m을 10으로 나눈 나머지로 구할 수 있다. 십의 자리는 100으로 나눈 나머지를 10으로 나누면 몫이다. 백의 자리는 100을 나눈 몫으로 구할 수 있다.
- 연산할 때 연산자마다의 우선 순위가 있다. 우선 순위에 대해선 3.참고에 정리했다. 만약 우선순위가 헷갈린다면 ()를 통해 분리해주면 된다.
◽ 풀이 2 : BufferedReader, System.out.println(); 사용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader kb = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(kb.readLine());
int m = Integer.parseInt(kb.readLine());
System.out.println(n * (m % 10));
System.out.println(n * (m % 100/10));
System.out.println(n * (m / 100));
System.out.println(n * m);
kb.close();
}
}
- BufferedReader은 Buffer에 있는 IO 클래스로 데이터를 버퍼에 저장해두었다가 한번에 입력하는 방식으로 동작한다.
- 데이터를 하나씩 입력하는 것이 아니라 한번에 입력하므로 속도가 빠르다.
- 입출력이 많은 코드, 데이터의 양이 많은 경우에서 지향하는 방식이다.
- BufferedWriter을 사용하지 않았다. 그 이유는 BufferedWriter/BufferedReader는 String의 형태로만 입출력이 가능하기 때문에 int 형의 값을 출력하려면 다시 String형으로 변환해주어야 한다. 두번 파싱이 들어가는 것보다 그냥 System.out.print()를 쓰는것이 속도면에서 좀 더 효율적이기 때문에 System.out.print()를 사용하였다.
- BufferedReader의 경우 BufferedWriter과는 약간 다르게 close()의 중요도가 낮다. 하지만 최적화 관점에서 close()하여 스트림을 닫아주는 것이 좋다.
- 자바에서는 Garbage Collection/Collector를 통해서 자바 내의 객체 및 리소스들이 자동으로 정리되기 때문에 close()를 하지 않아도 큰 문제가 발생하진 않는다. 하지만, Garbage Collection이 자동으로 모두 완료될때까지 BufferedReader에 할당된 리소스들이 그대로 유지되고 있기 때문에 최적화면에서 사용을 다한 BufferedReader들은 close()를 선언하여 스트림을 닫아주는 것이 좋다.
- StringTokenizer을 사용하지 않았다. 이유는 입력이 공백으로 구분되는 것이아니라 한줄씩 구분되어 들어오기 때문이다. 만약 공백으로 두 숫자가 구분된다면 StringTokenizer을 사용해 분리해주어야 한다.
◽ 속도 비교
- 1번 풀이 :
- 2번 풀이 :
- 지금까지 BufferedWriter와 System.out.print()의 차이는 출력양이 적어 차이가 거의 없었지만, Scanner와 BufferedReader의 경우 속도차이가 확연하게 다르다는 것을 볼 수 있다.
- Scanner보다 BufferedReader을 사용한 경우가 훨씬 더 빠르다.
- String형이 아닌 Int형의 출력이므로 BufferedReader+BufferedWriter보단 BufferedReader+System.out.print()가 속도면에서 좀 더 빠르다.(형변환 때문에)
3. 참고
* BufferedReader와 BufferedWriter에 대해서
[Java] 빠른 입출력 : BufferedReader & BufferedWriter