FastScanner — ускоряем чтение данных

Стандартный класс 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();
}
Поделиться данной статьей через:  

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.