2011-06-07 26 views
8

के साथ एक टेक्स्ट फ़ाइल में पढ़ना और सॉर्ट करना मैं जावा 5 & जावा 6 का उपयोग करने के लिए अपने जावा कौशल को अपग्रेड करने का प्रयास कर रहा हूं। मैं कुछ प्रोग्रामिंग अभ्यासों के साथ खेल रहा हूं। मुझे एक टेक्स्ट फ़ाइल से अनुच्छेद में पढ़ने और शब्दों की एक क्रमबद्ध (अवरोही) सूची आउटपुट करने और प्रत्येक शब्द की गिनती आउटपुट करने के लिए कहा गया था।अधिक कुशल या अधिक आधुनिक? जावा

मेरा कोड नीचे है।

मेरे प्रश्न हैं:

  1. मेरी फ़ाइल इनपुट दिनचर्या JVM संसाधनों का सबसे सम्मानजनक है?

  2. क्या फ़ाइल सामग्री को पढ़ने और सामग्री को संग्रह में लाने के संबंध में कदमों को काटना संभव है जो शब्दों की एक क्रमबद्ध सूची बना सकता है?

  3. क्या मैं संग्रह कक्षाओं का उपयोग कर रहा हूं और सबसे प्रभावी तरीका इंटरफ़ेस कर सकता हूं?

किसी भी राय के लिए धन्यवाद। मैं बस कुछ मजा करने और अपने प्रोग्रामिंग कौशल में सुधार करने की कोशिश कर रहा हूं।

import java.io.*; 
import java.util.*; 

public class Sort 
{ 
    public static void main(String[] args) 
    { 
     String sUnsorted  = null; 
     String[] saSplit   = null; 

     int iCurrentWordCount = 1; 
     String currentword  = null; 
     String pastword   = ""; 

     // Read the text file into a string 
     sUnsorted = readIn("input1.txt"); 

     // Parse the String by white space into String array of single words 
     saSplit = sUnsorted.split("\\s+"); 

     // Sort the String array in descending order 
     java.util.Arrays.sort(saSplit, Collections.reverseOrder()); 


     // Count the occurences of each word in the String array 
     for (int i = 0; i < saSplit.length; i++) 
     { 

      currentword = saSplit[i]; 

      // If this word was seen before, increase the count & print the 
      // word to stdout 
      if (currentword.equals(pastword)) 
      { 
       iCurrentWordCount ++; 
       System.out.println(currentword); 
      } 
      // Output the count of the LAST word to stdout, 
      // Reset our counter 
      else if (!currentword.equals(pastword)) 
      { 

       if (!pastword.equals("")) 
       { 

        System.out.println("Word Count for " + pastword + ": " + iCurrentWordCount); 

       } 


       System.out.println(currentword); 
       iCurrentWordCount = 1; 

      } 

      pastword = currentword; 
     }// end for loop 

     // Print out the count for the last word processed 
     System.out.println("Word Count for " + currentword + ": " + iCurrentWordCount); 



    }// end funciton main() 


    // Read The Input File Into A String  
    public static String readIn(String infile) 
    { 
     String result = " "; 

     try 
     { 
      FileInputStream file = new FileInputStream (infile); 
      DataInputStream in = new DataInputStream (file); 
      byte[] b    = new byte[ in.available() ]; 

      in.readFully (b); 
      in.close(); 

      result = new String (b, 0, b.length, "US-ASCII"); 

     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 

     return result; 
    }// end funciton readIn() 

}// end class Sort() 

///////////////////////////////////////////////// 
// Updated Copy 1, Based On The Useful Comments 
////////////////////////////////////////////////// 

import java.io.*; 
import java.util.*; 

public class Sort2 
{ 
    public static void main(String[] args) throws Exception 
    { 
     // Scanner will tokenize on white space, like we need 
     Scanner scanner    = new Scanner(new FileInputStream("input1.txt")); 
     ArrayList <String> wordlist = new ArrayList<String>(); 
     String currentword   = null; 
     String pastword    = null; 
     int iCurrentWordCount   = 1;  

     while (scanner.hasNext()) 
      wordlist.add(scanner.next()); 

     // Sort in descending natural order 
     Collections.sort(wordlist); 
     Collections.reverse(wordlist); 

     for (String temp : wordlist) 
     { 
      currentword = temp; 

      // If this word was seen before, increase the count & print the 
      // word to stdout 
      if (currentword.equals(pastword)) 
      { 
       iCurrentWordCount ++; 
       System.out.println(currentword); 
      } 
      // Output the count of the LAST word to stdout, 
      // Reset our counter 
      else //if (!currentword.equals(pastword)) 
      { 
       if (pastword != null) 
        System.out.println("Count for " + pastword + ": " + 
                  CurrentWordCount); 

       System.out.println(currentword); 
       iCurrentWordCount = 1;  
      } 

      pastword = currentword; 
     }// end for loop 

     System.out.println("Count for " + currentword + ": " + iCurrentWordCount); 

    }// end funciton main() 


}// end class Sort2 
+0

आपकी पहली सी ++ पृष्ठभूमि है जो पहली चीज है। यदि आप अपने समाधान ऑब्जेक्ट उन्मुख बनाने का प्रयास करते हैं, तो भी आप व्यायाम से अधिक लाभ प्राप्त कर सकते हैं, भले ही प्रश्न विशेष रूप से इसके लिए नहीं पूछें। इसे अधिक ऑब्जेक्ट-ओरिएंटेड बनाने से आप लॉजिकल क्लास में कार्यक्षमता को समूहबद्ध करने और अधिक सुविधाजनक विधि कॉल के पीछे कार्यान्वयन विवरण छुपाने के बारे में सोचेंगे। उस ने कहा, आपके कोड को और अधिक पढ़ने और अपने प्रश्न को अधिक सीधे संबोधित करने का समय ... –

+2

आपके नामकरण सम्मेलन आधुनिक जावा के लिए अत्याचारी हैं। हंगेरियन नोटेशन जो कि संगत नहीं है, किसी भी संस्करण के जावा के लिए मूर्ख नहीं है! सीधे 'ऐरे' का उपयोग करके भी फेंक दिया जाता है, वहां 'सूची' और' सेट 'कक्षाएं होती हैं जो अधिक मूर्खतापूर्ण होती हैं। –

+0

जारोड। मैं हंगेरियन नोटेशन के बारे में टिप्पणी को समझता हूं। इस स्थिति में एक ऐरे का उपयोग करने से सूची या सेट कक्षाएं बेहतर क्यों हैं? – Steve

उत्तर

4
  1. वहाँ जावा में एक फ़ाइल में सभी शब्दों में पढ़ने के अधिक मुहावरेदार तरीके हैं। BreakIterator इनपुट से शब्द में पढ़ने का एक बेहतर तरीका है।

  2. लगभग सभी मामलों में Array के बजाय List<String> का उपयोग करें। ऐरे तकनीकी रूप से Collection API का हिस्सा नहीं है और List, Set और Map के रूप में कार्यान्वयन को प्रतिस्थापित करना उतना आसान नहीं है।

  3. आपको पर चलने के बजाय Map<String,AtomicInteger> का उपयोग करना चाहिए। AtomicIntegerInteger के विपरीत उत्परिवर्तनीय है ताकि आप केवल एक ही ऑपरेशन में incrementAndGet() कर सकें जो थ्रेड सुरक्षित हो। SortedMap कार्यान्वयन आपको शब्दों की गणना के साथ-साथ शब्दों को भी देगा।

  4. Make as many variables, even local ones final as possible. और उनको उपयोग करने से पहले उन्हें सही घोषित करें, शीर्ष पर नहीं, जहां उनका इच्छित गुंजाइश खो जाएगा।

  5. डिस्क IO करते समय आपको अपने डिस्क ब्लॉक आकार के एकाधिक के बराबर उचित बफर आकार के साथ लगभग हमेशा BufferedReader या BufferedStream का उपयोग करना चाहिए।

उस ने कहा, जब तक आपके पास "सही" व्यवहार न हो, माइक्रो ऑप्टिमाइज़ेशन के साथ स्वयं से चिंता न करें।

2
  • SortedMap प्रकार हो सकता है कुशल पर्याप्त स्मृति के लिहाज से प्रपत्र SortedMap<String,Integer>
  • आप को तोड़ने के लिए Scanner प्रकार के ग्राहक सीमांकक प्रदान कर सकते हैं (विशेष रूप से अगर शब्द मायने रखता है 128 के तहत होने की संभावना है) में यहाँ का उपयोग करने के java.text पैकेज या आईसीयू परियोजना देखते हैं - धाराओं

कैसे आप डेटा का इलाज करना चाहते हैं पर निर्भर करता है, आप भी विराम चिह्न पट्टी या एक ब्रेक इटरेटर के साथ और अधिक उन्नत शब्द अलगाव के लिए जाने के लिए चाहते हो सकता है।

इसके अलावा - जब आप उन्हें पहले असाइन करते हैं और अवांछित शून्य मान असाइन करना बंद करते हैं तो मैं चर घोषित करने की अनुशंसा करता हूं। Integer की अचल और autoboxing के व्यवहार, इस हो सकता है result in excessive object instantiation बड़े डेटा सेट के लिए के कारण

void increment(Map<String, Integer> wordCountMap, String word) { 
    Integer count = wordCountMap.get(word); 
    wordCountMap.put(word, count == null ? 1 : ++count); 
} 

:


विस्तार करने के लिए, तो आप इस तरह एक नक्शे में शब्दों भरोसा कर सकते हैं। एक वैकल्पिक होगा (के रूप में अन्य सुझाव है) एक परिवर्तनशील int आवरण का उपयोग करने के (जिनमें से AtomicInteger एक रूप है।)

+0

+1। मैं नियमित रूप से पुराने हैश मैप सोच रहा था, लेकिन ऑर्डर्डमैप चीजों को और भी आसान बना देगा। –

+0

हाय मैकडॉवेल; स्कैनर का उपयोग एक साफ विचार की तरह लगता है। मानचित्र प्रमुख मूल्य जोड़ों को संग्रहीत करने के लिए हैं और मैं केवल एकल, गैर-युग्मित वस्तुओं की एक सूची प्राप्त करना चाहता हूं। क्या आप सुझाव दे रहे हैं कि मैं अपने एपीआई के लिए मानचित्र का उपयोग करता हूं और केवल एक ही स्ट्रिंग को कुंजी और मान देता हूं? – Steve

+0

@ user787832 - आप शब्दों (कुंजी) और शब्द गणना (मान) को स्टोर करने के लिए मानचित्र का उपयोग कर सकते हैं। – McDowell

0

आप अपने होमवर्क असाइनमेंट के लिए Guava का उपयोग कर सकते हैं? Multiset गिनती संभालती है। विशेष रूप से, LinkedHashMultiset उपयोगी हो सकता है।

+0

हाय डीजेजी; मानो या नहीं, यह होमवर्क नहीं है। यह सिर्फ मुझे "कोड काटा" पर गुगल करके खुद को उकसाने की कोशिश कर रहा है। मुझे अमरूद से अवगत नहीं था। धन्यवाद। मैं इस पल के लिए मानक जावा से चिपकने की कोशिश कर रहा हूं। – Steve

0

कुछ अन्य बातों आपको दिलचस्प लग सकते:

आप एक BufferedReader (यह पाठ अगर केवल) इस्तेमाल कर सकते हैं फ़ाइल को पढ़ने के लिए।

यह:

for (int i = 0; i < saSplit.length; i++){ 
    currentword = saSplit[i]; 
    [...] 
} 

, एक विस्तारित के लिए लूप (जावा foreach) का उपयोग किया जा सकता है पता चला की तरह here

if (currentword.equals(pastword)){ 
    [...] 
} else if (!currentword.equals(pastword)) { 
    [...] 
} 

आपके मामले में, आप बस का उपयोग कर सकते एक भी else तो हालत फिर से चेक नहीं किया गया है (यदि शब्द ही नहीं हैं, वे केवल अलग हो सकता है क्योंकि)।

if (!pastword.equals("")) 

मैं length का उपयोग कर लगता है कि तेजी से यहाँ है:

if (!pastword.length == 0) 
+0

उस अंतिम बिंदु के लिए, यदि आप _are_ का उपयोग करने जा रहे हैं .equals(), आपको निरंतर पहले उपयोग करना चाहिए - यानी, 'if ("" .equals (pastword))' - संभावित 'NullPointerException' से बचने के लिए। –

0

इनपुट पद्धति:

यह अपने आप पर आसान बनाएं और बाइट्स के बजाय पात्रों के साथ सीधे व्यवहार। उदाहरण के लिए, आप FileReader का उपयोग कर सकते हैं और संभवतः इसे BufferedReader के अंदर लपेट सकते हैं। कम से कम, मैं InputStreamReader को देखने का सुझाव दूंगा, क्योंकि बाइट्स से वर्णों में बदलने के कार्यान्वयन पहले ही आपके लिए किया जा चुका है। मेरी वरीयता Scanner का उपयोग करेगी।

मैं null लौटने या readIn() विधि से अपवाद फेंकना पसंद करूंगा।अपवादों का प्रवाह प्रवाह के लिए उपयोग नहीं किया जाना चाहिए, लेकिन, यहां, आप कॉलर को एक महत्वपूर्ण संदेश भेज रहे हैं: आपके द्वारा प्रदान की गई फ़ाइल मान्य नहीं थी। जो मुझे एक और बिंदु पर लाता है: इस बात पर विचार करें कि क्या आप वास्तव में सभी अपवादों को पकड़ना चाहते हैं, या केवल कुछ प्रकार के हैं। आपको सभी चेक अपवादों को संभालना होगा, लेकिन आप उन्हें अलग-अलग संभालना चाहते हैं।

संग्रह:

आप कर रहे हैं वास्तव में संग्रह वर्गों का उपयोग नहीं है, तो आप एक सरणी का उपयोग कर रहे हैं। आपका कार्यान्वयन ठीक लगता है, लेकिन ...

निश्चित रूप से इस समस्या को संभालने के कई तरीके हैं। आपकी विधि - क्रमशः तुलना करने के साथ सॉर्टिंग - औसत पर ओ (nlogn) है। यह निश्चित रूप से बुरा नहीं है। और शायद - - एक Map कार्यान्वयन का उपयोग कर के (जैसे HashMap के रूप में) एक तरह से डेटा जबकि केवल में हे (एन) पाठ से गुजरने की जरूरत है (HashMap के get() और put() स्टोर करने के लिए को देखो तरीकों हे हैं (1))।

+0

हम्म ... जब मैंने लिखा कि मैंने यह नहीं देखा कि आपका आउटपुट क्रमबद्ध क्रम में होना था। दुर्भाग्य से, आप ओ (nlogn) से नीचे नहीं जा रहे हैं, लेकिन मुझे अभी भी लगता है कि 'मानचित्र' कार्यान्वयन का उपयोग बेहतर होगा। –

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