2011-08-13 12 views
47

मैं Scanner(System.in) का उपयोग कर मानक से अंतरिक्ष या न्यूलाइन द्वारा अलग किए गए पूर्णांक का समूह पढ़ रहा हूं।जावा में System.in से पढ़ने का सबसे तेज़ तरीका क्या है?

जावा में ऐसा करने का कोई तेज़ तरीका है?

+0

संभावित डुप्लिकेट [जावा में फ़ाइल से बड़ी मात्रा में डेटा पढ़ें] (http: // stackoverflow।कॉम/प्रश्न/26 9 3223/फ़ाइल-इन-जावा से डेटा-पढ़ने-बड़ी-मात्रा-डेटा) – Crozin

+0

प्रति सेकंड कितने लाख पूर्णांक पढ़ने की आवश्यकता है? यदि आपके पास कुछ मिलियन से भी कम है तो मैं इसके बारे में ज्यादा चिंता नहीं करता। –

+0

मैं प्रोग्रामिंग प्रतियोगिताओं में इस मुद्दे के साथ समस्याओं में भाग गया। यह असामान्य नहीं है कि आपको हजारों संख्याओं के साथ हजारों समस्याएं मिलती हैं (कुछ विश्वास प्राप्त करने के लिए कि आप बुरी जटिलता के समाधान से दूर नहीं हैं)। – aioobe

उत्तर

71

जावा में ऐसा करने का कोई तेज़ तरीका है?

हां। स्कैनर काफी धीमा है (कम से कम मेरे अनुभव के अनुसार)।

यदि आपको इनपुट को सत्यापित करने की आवश्यकता नहीं है, तो मेरा सुझाव है कि आप बस BufferedInputStream में स्ट्रीम को लपेटें और String.split/Integer.parseInt जैसे कुछ का उपयोग करें।


एक छोटा सा तुलना:

पढ़ना 17 मेगाबाइट (4,233,600 संख्या) इस कोड को

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

का उपयोग कर मेरी मशीन 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 सेकंड ले लिया।

आगे कोड अप खिलवाड़ करके आप इसे काफी आसानी से लगभग 0.1 सेकंड के लिए नीचे प्राप्त कर सकते हैं (String.indexOf/String.substring साथ line से अधिक पुनरावृत्ति), लेकिन मुझे लगता है कि मैं अपने प्रश्न का उत्तर है और मैं में इस बारी नहीं करना चाहते कुछ कोड गोल्फ।

+0

हालांकि आपके कोड में ऐसे अव्यवस्था को जोड़ने के लिए आपके पास बेहतर कारण है। –

+12

String.split स्ट्रिंगटोकनाइज़र जितना तेज़ नहीं है। सबसे कुशल कोड प्राप्त करने के लिए, 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(" ") से पहले से तेज था। (समस्या को 1 लाख प्रत्येक के 1 लाख पूर्णांकों पढ़ने शामिल किया गया।)

2

मैं एक छोटे से InputReader वर्ग जो सिर्फ जावा के स्कैनर की तरह काम करता है, लेकिन कई परिमाण द्वारा गति में यह बेहतर साबित, वास्तव में बनाई गई है, यह BufferedReader रूप से बेहतर साबित कुंआ।

enter image description here

यहाँ सिस्टम से आने वाले सभी संख्याओं का योग पाने की दो अलग-अलग तरीके हैं: यहाँ एक बार ग्राफ जो InputReader वर्ग मैं मानक इनपुट से विभिन्न प्रकार के डेटा को पढ़ने बनाया है के प्रदर्शन से पता चलता है 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() 'BufferedReader.readLine()' की तुलना में OpenJKD8 के साथ उल्लेखनीय रूप से तेज़ नहीं है। बफर आकार 2048 था, धारा की लंबाई 2.5 एमबी थी। लेकिन इससे भी बदतर: कोड ब्रेक (यूटीएफ -8) चरित्र एन्कोडिंग। –

संबंधित मुद्दे