2011-12-06 8 views
10
public Object[] toArray() { 
    // Estimate size of array; be prepared to see more or fewer elements 
    Object[] r = new Object[size()]; 
    Iterator<E> it = iterator(); 
    for (int i = 0; i < r.length; i++) { 
     if (! it.hasNext()) // fewer elements than expected 
      return Arrays.copyOf(r, i); 
     r[i] = it.next(); 
    } 
    return it.hasNext() ? finishToArray(r, it) : r; 
} 

के कार्यान्वयन में कोड का उपयोग AbstractCollection.toArray विधि के कार्यान्वयन का कोड यहां दिया गया है।सारकोलेक्शन के टूएरे विधि

if (! it.hasNext()) // fewer elements than expected 
    return Arrays.copyOf(r, i); 

मुझे उपरोक्त कोड के उपयोग को समझ में नहीं आता है। मुझे संदेह है कि विधि का उपयोग करते समय आकार बदलने से बचने के लिए कोड का उपयोग किया जाता है। तो मेरे पास दो प्रश्न हैं:

  1. मुझे क्या संदेह है कि सही या गलत है? यदि यह गलत है, तो इस कोड का उपयोग क्या है?
  2. यदि यह सच है, तो विधि को लागू करने के दौरान आकार बदलने से कौन सी स्थिति बदल सकती है?

उत्तर

5

ठीक है, विधि के जावाडोक यह सब sais:

/** 
    * {@inheritDoc} 
    * 
    * <p>This implementation returns an array containing all the elements 
    * returned by this collection's iterator, in the same order, stored in 
    * consecutive elements of the array, starting with index {@code 0}. 
    * The length of the returned array is equal to the number of elements 
    * returned by the iterator, even if the size of this collection changes 
    * during iteration, as might happen if the collection permits 
    * concurrent modification during iteration. The {@code size} method is 
    * called only as an optimization hint; the correct result is returned 
    * even if the iterator returns a different number of elements. 
    * 
    * <p>This method is equivalent to: 
    * 
    * <pre> {@code 
    * List<E> list = new ArrayList<E>(size()); 
    * for (E e : this) 
    *  list.add(e); 
    * return list.toArray(); 
    * }</pre> 
    */ 

मैं दो दिलचस्प बातें यहाँ उल्लेख करना लगता है:

  1. हाँ, तुम सही हो, जावाडोक sais के रूप में, इस विधि को सही समय पर संशोधित करने के लिए तैयार किया गया है भले ही संग्रह को मध्य समय में संशोधित किया गया हो। यही कारण है कि प्रारंभिक आकार सिर्फ एक संकेत है। इटरेटर का उपयोग "समवर्ती संशोधन" अपवाद से बचने को भी सुनिश्चित करता है।

  2. एक बहु थ्रेडेड स्थिति की कल्पना करना बहुत आसान है जहां एक थ्रेड संग्रह से तत्व जोड़ता/निकालता है जबकि एक अलग थ्रेड उस पर "toArray" विधि को कॉल करता है। ऐसी स्थिति में, यदि संग्रह थ्रेड सुरक्षित नहीं है (जैसे Collections.synchronizedCollection(...) विधि के माध्यम से प्राप्त किया गया है, या इसके प्रति मैन्युअल रूप से सिंक्रनाइज़ एक्सेस कोड बनाकर) आप उस स्थिति में आ जाएंगे जहां यह संशोधित है और एक ही समय में ऐरे-एड है।

0

तुम ठीक कह रहे, सरणी के आकार के साथ आरंभ नहीं हो जाता() यदि हां, तो किसी भी तत्व जबकि सरणी डाला जा रहा है निकाल दिया जाता है, तो आप इस जाँच से लाभ होगा।

संग्रह सुरक्षित थ्रेड नहीं है, तो एक और धागा निकाल सकते हैं(), जबकि यात्रा प्रगति :-)

0

में है, इसे आम तौर गारंटी है कह सकते हैं डिफ़ॉल्ट रूप से कर रहे हैं (सभी java.util के लिए उदाहरण के लिए। * Collection वर्ग) कि एक संग्रह पुन: चालू होने पर नहीं बदलेगा (अन्यथा एक ConcurrentModificationException फेंकता है) यह सभी संग्रहों के लिए गारंटी नहीं है। इसलिए एक धागा तत्वों को जोड़ने या निकालने के लिए संभव है जबकि एक थ्रेड ऑर्रे() को कॉल कर रहा है, इस प्रकार संग्रह के आकार को बदल रहा है और इसलिए परिणामी सरणी है। वैकल्पिक रूप से, कुछ कार्यान्वयन केवल अनुमानित आकार लौटा सकता है। यदि संग्रह के अंत की उम्मीद आकार से पहले पहुँच गया था

  1. इन दो पंक्तियों को चेक (आकार का परिणाम() फोन जो r.length को परिभाषित करता है) पर पहुंच गया था:

    इसलिए, सवाल का जवाब देने। यदि ऐसा है, उचित आकार के साथ सरणी आर की एक प्रति बनाई जाएगी। याद रखें कि एक सरणी का आकार बदलना संभव नहीं है।

  2. जैसा कि कहा गया है, संग्रह के लिए अनुबंध के बाद से विभिन्न संभावनाएं काफी ढीली हैं। मल्टी-थ्रेडिंग, आकार() और अन्य के अनुमानित परिणाम।

+0

शामिल नहीं होना चाहिए कि ", इसे आम तौर गारंटी है (सभी java.util के लिए उदाहरण के लिए। * Collection वर्ग) है कि एक संग्रह, जबकि यह दोहराया है परिवर्तन नहीं होगा" इस गणन के साथ सच था । इटरेटर सटीक विपरीत की गारंटी देता है: यह ठीक है (और इसकी उम्मीद है) पुनरावृत्त होने पर संग्रह को संशोधित करें। जावाडोक से: "संग्रह पर एक पुनरावर्तक। इटरेटर जावा संग्रह ढांचे में गणना का स्थान लेता है। इटरेटर दो तरीकों से गणनाओं से अलग होते हैं: इटरेटर कॉलर को पुनरावृत्ति के दौरान अंतर्निहित संग्रह से तत्वों को हटाने के लिए अनुमति देते हैं । " –

+0

@AndreiBodnarescu Iterator's remove() विधि के लिए यह सच है। हालांकि इसे आम तौर पर संग्रह के निकालने() को उपयोग करने की अनुमति नहीं दी जाती है (कोशिश करते समय (iter.hasNext()) संग्रह .remove (iter.next()); ') – sfussenegger

+0

https://gist.github.com/1438902 देखें मेरे लिए क्या मतलब था – sfussenegger

3

मैं सिर्फ उल्लेख करने के लिए कि javadoc के अनुसार, विधि size() अधिकतम Integer.MAX_VALUE लौट सकते हैं चाहता हूँ। लेकिन अगर आपके संग्रह में अधिक तत्व हैं तो आपको उचित आकार नहीं मिल सकता है।

+0

यह एक अच्छा अवलोकन है। मुझे लगता है कि इस मामले में आपको संग्रह को पार करने के लिए एक इटरेटर का उपयोग करके खुद को अनुमानित करना होगा। –

+1

यह उत्तर इस प्रश्न के लिए बेकार है क्योंकि जावा सरणी में Integer.MAX_VALUE की तुलना में अधिक तत्व नहीं हो सकते हैं। अन्यथा आप उन्हें कैसे अनुक्रमित करेंगे? :) –

0

Andrei मुख्य उत्तर है। corsair Integer.MAX_VALUE के बारे में एक उत्कृष्ट बिंदु उठाता है।

पूर्णता के लिए, मैं जोड़ देगा toArray विधि सहित किसी भी संग्रह पर काम माना जाता है: एक गाड़ी आकार विधि के साथ

  1. सरणियों;
  2. गतिशील सरणी - संग्रह की सामग्री अन्य धागे (समरूपता), समय, या यादृच्छिक संख्याओं के आधार पर बदल सकती है। छद्म कोड

    संग्रह < संग्रह> चीजेंकैथोलिक कैनियट; // अगर आज शुक्रवार की मांस

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