java 快速io_java 最快的input (ACM) Java高效IO
java 最快的input
問題: Scanner 非常非常非常慢
使用Scanner來輸入非常方便,但很慢. 使用 BufferedReader 和 StringTokenizer 會更快, 但是在比賽中沒有時間打這么繁雜的代碼. 我們是否可以讓java在ACM中
用起來更加簡便呢?
java的輸入比C繁雜太多了 (如果你使用BufferedReader會更糟糕)
JavaC/C++
Scanner input =
new Scanner(System.in);
double x = input.nextDouble();
double x;
scanf("%lf",&x);
有多慢?
我測試從文件中讀取 10,000,000個?int?或者?double. 用時時如下表. 我的運行環境是 Intel Core2 Duo 2.4GHz cpu, Windows XP Pro SP3, Sun JDK 6.0r22, 和GNU gcc 4.5.2.
表格1. 從文件中讀取 10,000,000 int值用時
Input MethodTime (sec)
C scanf("%d", &arg)
3.78
Scanner.parseInt()
29.52
BufferedReader + inline Integer.parseInt
2.89
BufferedReader + Reader.nextInt method
3.01
表格2.從文件中讀取 10,000,000 double值用時
Input MethodTime (sec)
C scanf("%lf", &arg)
11.9
Scanner.parseDouble()
66.86
BufferedReader + inline Double.parseDouble
3.06
BufferedReader + Reader.nextDouble method
3.14
列表1. 分別用Scanner 和 BufferedReader用以下示例代碼來讀取?。?我們分割輸的一行為 string tokens,c因為一行可能包括
多個值。分割輸入行來說,?StringTokenizeris 比?string.split()快4倍以上.
/** 用Scanner讀取指定個數的整數*/
static int scanInteger(int count) {
Scanner scanner = new Scanner(input);
int last = 0;
while (count-- > 0) {
last = scanner.nextInt();
}
return last;
}
/** 使用BufferedReader讀取指定個數的整數 */
static int readIntegers(int count)
throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(input) );
StringTokenizer tokenizer = new StringTokenizer("");
int last = 0;
while (count-- > 0) {
if (! tokenizer.hasMoreTokens() ) {
tokenizer = new StringTokenizer(reader.readLine());
}
last = Integer.parseInt(tokenizer.nextToken());
}
return last;
}
創建可重用代碼
Java如何減輕讀取輸入的負擔呢? Java和C/C++比較有如下優勢: 更少語法錯誤, 也許更少邏輯錯誤, 更好的代碼生成 和 在Eclipse中調試.
為了使java更容易使用, 讓我們把輸入代碼放到一個單獨的類吧. (你可以在源文件中放多個類, 前提是只有一個類是“public”的。) 我們可以復制粘貼?Reader?類到每一個ACM 編程任務中, 所以我們在競賽中只要寫一次。 當其他人在研究問題的時候,其中一個人就可以寫好它。
列表2 只是其中一個例子. 如果你有更短,更有效的代碼一定要告訴我. 我用了?StringTokenizer?代替?string.split()?因為StringTokenizer更快。 我使用了靜態方法, 好處就是, 我們不必創建Reader的對象?, 并且使用默認訪問權限(因為在同一個包下),所以就不用花時間打“public”。在我的測試中, 把輸入方法放到一個單獨的類中對速度基本沒有影響?(有點驚訝)。但是對于余下的編程任務來說, 這會代碼的提高可重用性和簡便性,。
好像還是挺長的, 但是你只要打一次,以后可以就復制粘貼。
所以在你的 ACM 編程任務中, 你可以寫這樣的代碼:
Reader.init( System.in );
double x = Reader.nextDouble();
int n = Reader.nextInt();
列表2. 讀取int和double的可重用類。
/** 讀取int和double的類 */
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
/** 調用這個方法來初始化reader,即InputStream*/
static void init(InputStream input) {
reader = new BufferedReader(
new InputStreamReader(input) );
tokenizer = new StringTokenizer("");
}
/** 獲取下一段文本 */
static String next() throws IOException {
while ( ! tokenizer.hasMoreTokens() ) {
//TODO add check for eof if necessary
tokenizer = new StringTokenizer(
reader.readLine() );
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt( next() );
}
static double nextDouble() throws IOException {
return Double.parseDouble( next() );
}
}
翻譯by kucoder
總結
以上是生活随笔為你收集整理的java 快速io_java 最快的input (ACM) Java高效IO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java if和else if的区别_关
- 下一篇: java过时_Java 语言的几个缺陷之