2012-04-12 23 views
172

को देखते हुए Iterator<Element>, हम कैसे है कि संभव Iterator को ArrayList<Element> (या List<Element>) सबसे अच्छा में और सबसे तेजी से तरह से परिवर्तित कर सकते हैं, ताकि हम उस पर इस तरह के रूप get(index), add(element), आदि पर ArrayList के संचालन का उपयोग कर सकते ।Convert इटरेटर ArrayList को

उत्तर

287

बेहतर Guava की तरह एक पुस्तकालय का उपयोग करें:

import com.google.common.collect.Lists; 

Iterator<Element> myIterator = ... //some iterator 
List<Element> myList = Lists.newArrayList(myIterator); 

एक और अमरूद उदाहरण:

ImmutableList.copyOf(myIterator); 

या Apache Commons Collections:

import org.apache.commons.collections.IteratorUtils; 

Iterator<Element> myIterator = ...//some iterator 

List<Element> myList = IteratorUtils.toList(myIterator);  
+4

मुझे यह नहीं मिला। ArrayList किस तरह से लौटा, कहते हैं, Guava एक सामान्य ArrayList से बेहतर है? क्या वे इसे अधिक कुशल तरीके से करते हैं? भले ही यह अधिक कुशल है, यह वास्तव में आपकी परियोजना के लिए एक अतिरिक्त निर्भरता (और अधिक जटिलता) जोड़ने लायक है? – CorayThan

+6

@ कोरयहान कम कोड + परीक्षण विधियां। हालांकि मैं आपसे सहमत हूं कि मैं उस विधि का उपयोग करने के लिए अतिरिक्त निर्भरता नहीं जोड़ूंगा। लेकिन फिर, मेरी अधिकांश (बड़ी) परियोजनाएं या तो अमरूद या अपाचे कॉमन्स का उपयोग करती हैं ... – Renaud

+1

@ कोरयहान विभाजन और मेरे दोस्त को जीतें। एक पुस्तकालय द्वारा पहले से प्रदान की गई विधि क्यों लिखें और परीक्षण किया जाता है? हम बहुत सारे अपाचे कॉमन्स और अमरूद का उपयोग कर रहे हैं, वे बहुत ही अच्छे हैं और आपको समय और पैसा बचाने में मदद करते हैं। – Stephan

58

आप इस तरह एक नई सूची के लिए एक इटरेटर कॉपी कर सकते हैं:

Iterator<String> iter = list.iterator(); 
List<String> copy = new ArrayList<String>(); 
while (iter.hasNext()) 
    copy.add(iter.next()); 

संभालने है कि उस सूची में तार शामिल हैं। वास्तव में एक इटरेटर से एक सूची को फिर से बनाने का एक तेज़ तरीका नहीं है, आप इसे हाथ से घुमाने के साथ फंस गए हैं और प्रत्येक तत्व को उचित प्रकार की एक नई सूची में कॉपी कर रहे हैं।

संपादित करें:

यहाँ एक प्रकार सुरक्षित तरीके से एक नई सूची के लिए एक इटरेटर कॉपी करने के लिए एक सामान्य विधि है:

List<String> list = Arrays.asList("1", "2", "3"); 
Iterator<String> iter = list.iterator(); 
List<String> copy = copyIterator(iter); 
System.out.println(copy); 
> [1, 2, 3] 
4
List result = new ArrayList(); 
while (i.hasNext()){ 
    result.add(i.next()); 
} 
:

public static <T> List<T> copyIterator(Iterator<T> iter) { 
    List<T> copy = new ArrayList<T>(); 
    while (iter.hasNext()) 
     copy.add(iter.next()); 
    return copy; 
} 

इस तरह इसका इस्तेमाल

+0

क्या इस कोड के साथ है? यह –

+0

संकलित भी नहीं करता है कोड ठीक है। अपने मामले में मैं एक इटरेटर Maksim

+0

है, यह कोड में होना चाहिए जैसे @ ऑस्करलोपेज़ ने –

-2

यहां इस मामले में यदि आप सबसे तेज़ तरीका चाहते हैं तोबेहतर है।

10,000 runs का एक नमूना आकार से अधिक इटरेटर 40 ms लेता है जहां पाश के लिए के रूप में मानते हुए है यही कारण है कि उस सूची में शामिल है तार लेता 2 ms

 ArrayList<String> alist = new ArrayList<String>(); 
     long start, end; 

     for (int i = 0; i < 1000000; i++) { 
      alist.add(String.valueOf(i)); 
     } 

     ListIterator<String> it = alist.listIterator();  

     start = System.currentTimeMillis(); 
     while (it.hasNext()) { 
      String s = it.next(); 
     } 
     end = System.currentTimeMillis(); 

     System.out.println("Iterator start: " + start + ", end: " + end + ", delta: " 
      + (end - start)); 
     start = System.currentTimeMillis(); 
     int ixx = 0; 
     for (int i = 0; i < 100000; i++) { 
      String s = alist.get(i); 
     } 

     System.out.println(ixx); 
     end = System.currentTimeMillis(); 
     System.out.println("for loop start: " + start + ", end: " + end + ", delta: " 
      + (end - start)); 

+3

निश्चित रूप से 'फॉर' लूप का उपयोग करके और 'get (i)' के साथ किसी सूची के तत्वों तक पहुंचने से इटेटरेटर का उपयोग करने से तेज़ है ... लेकिन ओपी पूछ रहा था, लेकिन यह विशेष रूप से उल्लेख नहीं किया गया है कि _iterator_ को इनपुट के रूप में दिया जाता है। –

+0

@ ओस्कर मुझे खेद है। क्या मैं अपना जवाब हटा सकता हूं? – vikiiii

+0

यह आपका फोन है। मैं इसे अभी तक नहीं हटाऊंगा, यह जानकारीपूर्ण हो सकता है। जब लोग उन्हें कम करना शुरू करते हैं तो मैं केवल अपने उत्तरों को हटा देता हूं :) –

0

उपयोग गूगल guava!

Iterable<String> fieldsIterable = ... 
List<String> fields = Lists.newArrayList(fieldsIterable); 

++

+0

Iterator (Iterable नहीं) ArrayList –

18

तुम भी अपाचे commons-collections से IteratorUtils उपयोग कर सकते हैं, हालांकि यह जेनरिक का समर्थन नहीं करता: सादा जावा 8 के साथ

List list = IteratorUtils.toList(iterator); 
+0

में इसमें 2 toArray विधि भी है और 1 एक प्रकार स्वीकार करता है: http: //commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons /collections/IteratorUtils.html#toArray(java.util.Iterator, java.lang.Class) – dwana

5

सुंदर संक्षिप्त समाधान java.util.stream का उपयोग कर:

public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) { 
    return StreamSupport 
     .stream(
      Spliterators 
       .spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) 
     .collect(
       Collectors.toCollection(ArrayList::new) 
    ); 
} 
+0

क्या स्ट्रीम एपीआई का उपयोग करके इसे लिखने का एक और अधिक कॉम्पैक्ट तरीका है? लूप रास्ता सामान्य होने की तुलना में यह आसान नहीं लगता है। –

+26

मैं उस समाधान को "संक्षिप्त" नहीं कहूंगा। – Sergio

+0

@ सर्जीओ यही कारण है कि मैंने "सुंदर" लिखा था। हालांकि, इसे स्थानीय चर और केवल एक अर्धविराम की आवश्यकता नहीं है। आप स्थिर आयात के साथ इसे छोटा कर सकते हैं। – xehpuk

141

जावा 8 में, आप नएका उपयोग कर सकते हैंविधि है कि Iterator इंटरफेस जोड़ लिया गया है:

List<Element> list = new ArrayList<>(); 
iterator.forEachRemaining(list::add); 
+1

क्या मतलब है ':: '? इसका नाम क्या है? list.add() के लिए प्रत्यक्ष संदर्भ प्रतीत होता है; और कुछ java8 नई बात भी लगता है; और धन्यवाद! :) –

+11

@AquariusPower '8 'वाक्यविन्यास जावा 8 में नया है, और यह एक" विधि संदर्भ "को संदर्भित करता है, जो लैम्ब्डा का एक लघुरूप रूप है। अधिक जानकारी के लिए यहां देखें: http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html –

11
जावा 8 के साथ

आप इस समाधान का उपयोग कर सकते हैं:

Iterable<Element> iterator = createIterator(); 
List<Element> array = StreamSupport 
    .stream(iterator.spliterator(), false) 
    .collect(Collectors.toList()); 

मैं Collectors.toList()ArrayList उदाहरण बनाता है जानते हैं।

वास्तव में मेरी राय में, यह भी एक पंक्ति में अच्छा दिखता है।
उदाहरण के लिए यदि आप कुछ विधि से List<Element> वापस जाने के लिए की जरूरत है:

return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList()); 
+1

प्रश्न शुरुआती बिंदु के रूप में इटरेटर के बारे में है, Iterable नहीं। – Jaap

1

Cactoos से StickyList का प्रयास करें:

List<String> list = new StickyList<>(iterator); 

अस्वीकरण: मैं डेवलपर्स में से एक हूँ।

+0

यह सवाल का जवाब नहीं देता है। 'Iterable'! =' Iterator' – xehpuk

+0

@xehpuk मैंने उत्तर – yegor256

+0

ग्रेट अपडेट किया है, अब आपको शायद नए संस्करण के लिए जावाडॉक उत्पन्न करने और लिंक अपडेट करने की आवश्यकता है। :) – xehpuk

0

मैं सिर्फ एक उचित रूप में स्पष्ट समाधान करते रहे कि नहीं काम करेगा:

 
List list = Stream.generate(iterator::next) 
    .collect(Collectors.toList()); 

है ऐसा इसलिए है क्योंकि Stream#generate(Supplier<T>) केवल अनंत स्ट्रीम को बना सकता है, यह अपने तर्क NoSuchElementException फेंक की उम्मीद नहीं है (वो क्या है Iterator#next() अंत में करेंगे)।

The xehpuk's answer का उपयोग किया जाना चाहिए यदि इटरेटर → स्ट्रीम → सूची तरीका आपकी पसंद है।

0

इटरेटर में जावा 8 forEachRemaining विधि यहां इस्तेमाल किया जा सकता है:

List<Element> elementList = new ArrayList<>(); 
iterator.forEachRemaining(elementList::add); 
+1

यह वही है जो स्टुअर्ट मार्क्स [उत्तर] (https://stackoverflow.com/a/28491752/369450) कहता है कि साढ़े सालों से पोस्ट किया गया था इस जवाब से पहले। – cpburnz