2009-08-06 6 views
56

मैं क्यों नहीं कर सकते हैं:मैं जावा गणना पर foreach का उपयोग क्यों नहीं कर सकता?

Enumeration e = ... 
for (Object o : e) 
    ... 
+4

गणना 1 99 8 में जावा 1.2 में इटरेटर द्वारा प्रतिस्थापित की गई थी और विरासत समर्थन के लिए बनाए रखा गया है। वास्तविक सवाल यह है कि आप इसका उपयोग क्यों करना चाहते हैं। संभवतः क्योंकि आप एक पुस्तकालय का उपयोग करते हैं जो आपको ऐसा करने के लिए मजबूर करता है? –

+1

@ पीटर - हाँ, बाहरी पुस्तकालय उत्तर है। – ripper234

उत्तर

55

क्योंकि Enumeration<T>Iterable<T> विस्तार नहीं करता है। यहां एक example of making Iterable Enumerations है।

यह एक दिलचस्प सवाल क्यों है। यह वास्तव में आपका प्रश्न नहीं है लेकिन यह इस पर कुछ प्रकाश डालता है। Java Collections API Design FAQ से:

इटरेटर गणना क्यों बढ़ाता है?

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

मूल रूप से मुझे यह सुझाव देता है कि सूर्य अपने आप को गणना से दूर करना चाहता है, जो काफी प्रारंभिक जावा के साथ बहुत प्रारंभिक जावा है।

+14

अगला प्रश्न: गणनाएं क्यों नहीं हैं Iterable? http://stackoverflow.com/questions/27240/why-arent-enumerations-iterable –

+1

क्या दोनों के बीच कोई अर्थपूर्ण अंतर है? (मैं इटेरबल कक्षा से परिचित नहीं हूँ)? गणना पर काम के लिए क्यों नहीं है? – ripper234

+4

क्योंकि गणनाएं इटरेटर के समान हैं, Iterable नहीं (स्टैक ओवरफ्लो प्रश्न mmyers पोस्ट देखें)। एक कामकाज के रूप में, आप '(e.hasMoreElements();) {e.getNextElement() के लिए कर सकते हैं; } ' – Tim

3

नई शैली-के-लूप ("foreach") सरणी पर काम करता है, और Iterable इंटरफ़ेस को लागू करने वाली चीजें।

यह भी Iterable करने से Iterator के लिए और अधिक अनुरूप है, इसलिए इसे जब तक Iterator भी किया Enumeration के लिए समझ में foreach के साथ काम करने नहीं होगा (और यह नहीं है)। EnumerationIterator के पक्ष में भी निराश है।

+1

चलिए यहां शर्तों से सावधान रहें। एपीआई पर चर्चा करते समय बहिष्करण का मतलब कुछ विशिष्ट है। गणना का उपयोग निराश है, लेकिन यह _not_ बहिष्कृत है। – ykaganovich

+0

ykaganovich: अच्छा बिंदु। मैंने जवाब में पाठ को सही किया है। –

0

क्योंकि एक गणना (और इस इंटरफ़ेस से प्राप्त अधिकांश कक्षाएं) Iterable लागू नहीं करती हैं।

आप अपना खुद का रैपर वर्ग लिखने का प्रयास कर सकते हैं।

+2

आपको गणना के लिए एक रैपर नहीं लिखना चाहिए जो इसे इटरेटर के लिए ऐसे रैपर बनाने से कहीं अधिक इटरबल में बदल देता है। इटरेटर और गणना वस्तुओं पुनरावृत्ति के संबंध में राज्यव्यापी हैं। Iterables नहीं हैं। –

6

मैंने इस समस्या को दो बहुत ही सरल वर्गों के साथ हल किया है, एक Enumeration और एक Iterator के लिए। गणन आवरण इस प्रकार है:

static class IterableEnumeration<T> 
extends Object 
implements Iterable<T>, Iterator<T> 
{ 
private final Enumeration<T>  enumeration; 
private boolean      used=false; 

IterableEnumeration(final Enumeration<T> enm) { 
    enumeration=enm; 
    } 

public Iterator<T> iterator() { 
    if(used) { throw new IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); } 
    used=true; 
    return this; 
    } 

public boolean hasNext() { return enumeration.hasMoreElements(); } 
public T  next() { return enumeration.nextElement();  } 
public void remove() { throw new UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); } 
} 

कौन सा (जो मेरी प्राथमिकता है) या तो एक स्थिर उपयोगिता विधि के साथ इस्तेमाल किया जा सकता:

/** 
* Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop. 
*/ 
static public <T> Iterable<T> asIterable(final Enumeration<T> enm) { 
    return new IterableEnumeration<T>(enm); 
    } 

... 

for(String val: Util.asIterable(enm)) { 
    ... 
    } 

या वर्ग instantiating द्वारा:

for(String val: new IterableEnumeration<String>(enm)) { 
    ... 
    } 
31

संग्रह उपयोगिता वर्ग का उपयोग करके, गणना को पुन: प्रयोज्य बनाया जा सकता है:

Enumeration headerValues=request.getHeaders("mycustomheader"); 
List headerValuesList=Collections.list(headerValues); 

for(Object headerValueObj:headerValuesList){ 
... do whatever you want to do with headerValueObj 
} 
+2

पुनरावृत्ति शुरू करने से पहले तत्वों को एक नई सूची में कॉपी किया गया है, इस समाधान को लंबी गणनाओं से बचा जाना चाहिए। एक इटरेटर में एक गणना को बदलने वाले समाधानों में कम स्मृति ओवरहेड होता है। –

+0

@ एमानुअलबुर्ग लेकिन उनके दुष्प्रभाव हैं, क्योंकि गणनाएं राज्यव्यापी हैं। –

+1

यह अब तक का सबसे आसान जवाब है! कोई निर्भरता की आवश्यकता नहीं है, और स्पष्ट रूप से पठनीय। धन्यवाद! –

1

EnumerationIterable लागू नहीं करता है और इस तरह सीधे फ़ोरैच लूप में उपयोग नहीं किया जा सकता है।हालांकि Apache Commons Collections का उपयोग कर उसके साथ एक गणना से अधिक पुनरावृति करना संभव है:

for (Object o : new IteratorIterable(new EnumerationIterator(e))) { 
    ... 
} 

तुम भी Collections.list() साथ एक छोटी सिंटैक्स का उपयोग कर सकता है, लेकिन यह कम कुशल (तत्वों और अधिक स्मृति के उपयोग पर दो पुनरावृत्तियों) है:

for (Object o : Collections.list(e))) { 
    ... 
} 
+0

क्या आपका मतलब है [IteratorIterable] (http://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/iterators/IteratorIterable.html)? – luckyluke

+0

@luckyluke हां, धन्यवाद। मैंने उदाहरण तय किया। –

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