4 ответов:
есть ли быстрый способ сделать это в Java?
да. Сканер довольно медленно (по крайней мере по моему опыту).
Если вам не нужно проверять ввод, я предлагаю вам просто обернуть поток в BufferedInputStream и использовать что-то вроде
String.split/Integer.parseInt.
небольшое сравнение:
чтение 17 мегабайт (4233600 номеров) с помощью этого код
на своей машине 3,3 секунды. хотя этот фрагментScanner scanner = new Scanner(System.in); while (scanner.hasNext()) sum += scanner.nextInt();0.7 сек.BufferedReader bi = new BufferedReader(new InputStreamReader(System.in)); String line; while ((line = bi.readLine()) != null) for (String numStr: line.split("\s")) sum += Integer.parseInt(numStr);путем испортить код дальше (итерация над
lineСString.indexOf/String.substring) вы можете получить его примерно до 0,1 секунды довольно легко, но я думаю, что я ответил на ваш вопрос, и я не хочу превращать это в какой-то кодовый гольф.
Я создал небольшой InputReader класс, который работает так же, как сканер Java, но превосходит его по скорости на многие величины, на самом деле, он также превосходит BufferedReader. Вот гистограмма, которая показывает производительность класса InputReader, который я создал, читая различные типы данных из стандартного ввода:
вот два различных способа найти сумму всех чисел, поступающих из System.in использование Класс InputReader:
int sum = 0; InputReader in = new InputReader(System.in); // Approach #1 try { // Read all strings and then parse them to integers (this is much slower than the next method). String strNum = null; while( (strNum = in.nextString()) != null ) sum += Integer.parseInt(strNum); } catch (IOException e) { } // Approach #2 try { // Read all the integers in the stream and stop once an IOException is thrown while( true ) sum += in.nextInt(); } catch (IOException e) { }
вы можете узнать из
System.inв цифра за цифрой пути. Посмотрите на этот ответ: https://stackoverflow.com/a/2698772/3307066.я копирую код здесь (едва измененный). В основном, он читает целые числа, разделенные чем-либо, что не является цифрой. (Кредиты оригинальному автору.)
private static int readInt() throws IOException { int ret = 0; boolean dig = false; for (int c = 0; (c = System.in.read()) != -1; ) { if (c >= '0' && c <= '9') { dig = true; ret = ret * 10 + c - '0'; } else if (dig) break; } return ret; }в моей проблеме, этот код был приблизительно. 2 раза быстрее, чем при использовании
StringTokenizer, что было уже быстрее, чемString.split(" "). (Проблема заключалась в чтении 1 миллиона целых чисел до 1 миллиона каждый.)
в программной перспективе этот настроенный класс сканирования и печати намного лучше, чем встроенный сканер Java и классы BufferedReader.
import java.io.InputStream; import java.util.InputMismatchException; import java.io.IOException; public class Scan { private byte[] buf = new byte[1024]; private int total; private int index; private InputStream in; public Scan() { in = System.in; } public int scan() throws IOException { if(total < 0) throw new InputMismatchException(); if(index >= total) { index = 0; total = in.read(buf); if(total <= 0) return -1; } return buf[index++]; } public int scanInt() throws IOException { int integer = 0; int n = scan(); while(isWhiteSpace(n)) /* remove starting white spaces */ n = scan(); int neg = 1; if(n == '-') { neg = -1; n = scan(); } while(!isWhiteSpace(n)) { if(n >= '0' && n <= '9') { integer *= 10; integer += n-'0'; n = scan(); } else throw new InputMismatchException(); } return neg*integer; } public String scanString()throws IOException { StringBuilder sb = new StringBuilder(); int n = scan(); while(isWhiteSpace(n)) n = scan(); while(!isWhiteSpace(n)) { sb.append((char)n); n = scan(); } return sb.toString(); } public double scanDouble()throws IOException { double doub=0; int n=scan(); while(isWhiteSpace(n)) n=scan(); int neg=1; if(n=='-') { neg=-1; n=scan(); } while(!isWhiteSpace(n)&& n != '.') { if(n>='0'&&n<='9') { doub*=10; doub+=n-'0'; n=scan(); } else throw new InputMismatchException(); } if(n=='.') { n=scan(); double temp=1; while(!isWhiteSpace(n)) { if(n>='0'&&n<='9') { temp/=10; doub+=(n-'0')*temp; n=scan(); } else throw new InputMismatchException(); } } return doub*neg; } public boolean isWhiteSpace(int n) { if(n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true; return false; } public void close()throws IOException { in.close(); } }и настроенный класс печати может быть следующим
import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; public class Print { private BufferedWriter bw; public Print() { this.bw = new BufferedWriter(new OutputStreamWriter(System.out)); } public void print(Object object)throws IOException { bw.append("" + object); } public void println(Object object)throws IOException { print(object); bw.append("\n"); } public void close()throws IOException { bw.close(); } }

Comments