Стандартный класс
Scanner из пакета
java.util очень хорош для чтения небольшого кол-ва данных, но если кол-во данных большое и скорость чтения критична, то нужно самостоятельно реализовать более быстрый сканер. Ниже приведен пример такого сканера.
import java.io.*;
import java.util.StringTokenizer;
public class FastScanner {
BufferedReader br;
StringTokenizer st;
public FastScanner(){
init();
}
public FastScanner(String name) {
init(name);
}
public FastScanner(boolean isOnlineJudge){
if(!isOnlineJudge || System.getProperty("ONLINE_JUDGE") != null){
init();
}else{
init("input.txt");
}
}
private void init(){
br = new BufferedReader(new InputStreamReader(System.in));
}
private void init(String name){
try {
br = new BufferedReader(new FileReader(name));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public String nextToken(){
while(st == null || !st.hasMoreElements()){
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
public int nextInt(){
return Integer.parseInt(nextToken());
}
public long nextLong(){
return Long.parseLong(nextToken());
}
public double nextDouble(){
return Double.parseDouble(nextToken());
}
}
Примеры использования
Объявление FastScanner'а для чтения из консоли:
FastScanner scan = new FastScanner();
Объявление FastScanner'а для чтения из указанного файла:
FastScanner scan = new FastScanner("A.in");
Объявление FastScanner'а для чтения из консоли или из файла
input.txt
в зависимости от установленного свойства
ONLINE_JUDGE
FastScanner scan = new FastScanner(true);
Чтение данных:
int i = scan.nextInt();
long l = scan.nextLong();
double d = scan.nextDouble();
String token = scan.nextToken();
Быстрый вывод в консоль
Наряду с быстрым чтением входных данных, также важен быстрый вывод данных в консоль. Для ускорения вывода будем не сразу выводить данные в консоль с помощью
System.out, а с помощью
PrintWriter будем накапливать, и лишь потом сбрасывать данные в консоль командой
flush (что эффективнее). Сбрасывать данные лучше порциями среднего размера, чтобы соблюсти баланс между скорость и потребляемой памятью.
PrintWriter out = new PrintWriter(System.out);
out.println(result);
out.flush();
Сравним вывод одинаковых данных через обычный
System.out и через
PrintWriter.
Код ниже у меня отработал примерно за
2 секунды:
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
System.out.println(i * j);
}
}
А следующий код с буферизацией отработал существенно быстрее, за менее чем
0,7 секунды:
PrintWriter out = new PrintWriter(System.out);
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
out.println(i * j);
}
out.flush();
}