2011-08-13 68 views
47

我正在閱讀使用Scanner(System.in)從閱讀空間或換行符中分離出的一串整數。什麼是從Java中讀取System.in的最快方法?

在Java中這樣做有沒有更快的方法?

+0

可能的重複[從Java文件中讀取大量數據](http:// stackoverflow。com/questions/2693223/read-large-of-data-from-file-in-java) – Crozin

+0

你需要讀入每秒鐘多少百萬個整數?如果你有不到幾百萬的話,我不會擔心它太多。 –

+0

我在編程比賽中遇到了這個問題。通常每個成千上萬的數字都會遇到數千個問題實例(以獲得一定的信心,您不會錯過複雜度較低的解決方案)。 – aioobe

回答

71

在Java中這樣做有沒有更快的方法?

是的。掃描儀相當慢(至少根據我的經驗)。

如果你不需要驗證輸入,我建議你只是將流封裝在BufferedInputStream中,並使用諸如String.split/Integer.parseInt之類的東西。


一個小對比:

閱讀使用此代碼

Scanner scanner = new Scanner(System.in); 
while (scanner.hasNext()) 
    sum += scanner.nextInt(); 

17兆(4233600號),把我的機器3.3秒上。而這個片段

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); 

0.7秒

通過進一步搞亂的代碼(迭代lineString.indexOf/String.substring),你可以把它降低到0.1秒左右很容易,但我想我已經回答了你的問題,我不想把它變成一些代碼高爾夫。

+0

然而,你最好有一個很好的理由爲你的代碼添加這樣的混亂。 –

+12

String.split不如StringTokenizer快。爲了獲得最高效的代碼,使用StringTokenizer – kullalok

0

您可以通過數字方式從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; 
} 

在我的問題,這個代碼是約。比使用StringTokenizer快2倍,這已經快於String.split(" ")。 (問題涉案讀取高達100萬每1個百萬個整數。)

2

我創建了一個小InputReader類作品就像Java的掃描儀,但許多幅度優於它的速度,事實上,它優於BufferedReader中的好。這裏是一個棒形圖,我創建閱讀不同類型從標準輸入數據的InputReader類的性能:

enter image description here

以下是查出所有號碼從系統傳來的總和的兩種不同的方法.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) { } 
+0

不幸的是''InputReader.readLine()'在OpenJKD8中比'BufferedReader.readLine()'快不了。緩衝區大小爲2048,流長度爲2.5 MB。但更糟的是:代碼中斷(UTF-8)字符編碼。 –

相關問題