कन्वर्ट Iterator ArrayList के लिए


241

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

जवाबों:


360

अमरूद जैसे पुस्तकालय का बेहतर उपयोग करें :

import com.google.common.collect.Lists;

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

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

ImmutableList.copyOf(myIterator);

या अपाचे कॉमन्स संग्रह :

import org.apache.commons.collections.IteratorUtils;

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

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

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

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

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

5
रेनॉड और स्टीफ़न के साथ सहमत। इसके अलावा, यदि आप बिल्ड टूल का उपयोग कर रहे हैं, तो इन पुस्तकालयों को शामिल करना दुनिया का सबसे आसान काम है ... ALSO ... यदि आप वास्तव में उन्हें शामिल नहीं करना चाहते हैं तो आप Apache / Guava कोड के स्रोत पर जा सकते हैं और कॉपी करें कि उन्होंने वहां क्या किया है: अपना समय बर्बाद करने से बेहतर एफएआर ने सैकड़ों खूबसूरती से इंजीनियर और परीक्षण किए गए पहियों को फिर से स्थापित किया है जो पहले से ही वहां मौजूद हैं।
माइक कृंतक

238

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

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

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

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

कहा से iteratorआ रहा है यह एक अनसुलझे प्रतीक है
javadba

1
@javadba मूल प्रश्न यह था कि कैसे एक पुनरावृत्ति को परिवर्तित किया जाए जो आपके पास पहले से ही एक नए ArrayList में है। इस उदाहरण के प्रयोजनों के लिए, आपके पास पहले से मौजूद इट्रेटर कहा जाता है iterator
स्टुअर्ट मार्क्स

1
यह स्वीकृत उत्तर होना चाहिए, क्योंकि यह सबसे छोटा है और 3 पार्टी पुस्तकालयों पर निर्भर नहीं है
डैनियलकुआरा

64

आप इस तरह से एक नई सूची में एक पुनरावृत्त कॉपी कर सकते हैं:

Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
    copy.add(iter.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;
}

इसे इस तरह उपयोग करें:

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]

26

ध्यान दें कि Iterableऔर के बीच अंतर है Iterator

यदि आपके पास एक है Iterable, तो जावा 8 के साथ आप इस समाधान का उपयोग कर सकते हैं:

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

जैसा कि मुझे पता Collectors.toList()है कि ArrayListउदाहरण बनता है ।

वास्तव में मेरी राय में, यह एक पंक्ति में भी अच्छा लगता है।
उदाहरण के लिए यदि आपको List<Element>किसी विधि से लौटने की आवश्यकता है :

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

4
प्रश्न Iterator <Element> के बारे में है, एक प्रारंभिक बिंदु के रूप में, Iterable <Element> नहीं।
जप

1
उपरोक्त टिप्पणी से सहमत हैं। सुपर भ्रामक है कि आपने अपना नाम दिया Iterable iterator। वे पूरी तरह से अलग हैं।
स्टीफन हैरिसन

Java 8 में आप आसानी से एक Iteratorबैक का उपयोग Iterable करके परिवर्तित कर सकते हैं () -> iterator। यह इस तरह की स्थितियों में उपयोगी हो सकता है, लेकिन मुझे फिर से महत्वपूर्ण बात पर जोर देने दें: आप इस पद्धति का उपयोग केवल तभी कर सकते हैं जब कोई एकल उपयोग Iterable स्वीकार्य हो। iterable.iterator()एक से अधिक बार कॉल करने पर अप्रत्याशित परिणाम मिलेंगे। उपरोक्त उत्तर तब बनता हैIterator<Element> iterator = createIterator(); List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
neXus

21

आप IteratorUtilsअपाचे कॉमन्स-संग्रह से भी उपयोग कर सकते हैं , हालांकि यह जेनरिक का समर्थन नहीं करता है:

List list = IteratorUtils.toList(iterator);

इसमें 2 toArray मेथड भी है और 1 एक प्रकार स्वीकार करता है: commons.apache.org/proper/commons-collections/javadocs/… , java.lang.Class)
dwana

9

सादे जावा 8 का उपयोग करके सुंदर संक्षिप्त समाधान 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)
    );
}

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

37
मैं उस समाधान को "संक्षिप्त" नहीं कहूंगा।
सर्जियो

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

1
मैं कहूंगा iterator.forEachRemaining( list::add ), जावा 8 में भी नया, बहुत अधिक संक्षिप्त है। सूची चर को धक्का देना Collectorइस मामले में पठनीयता में सुधार नहीं करता है, क्योंकि इसे ए Streamऔर ए द्वारा समर्थित किया जाना है Spliterator
भेड़

1
@ शेरगियो यह छोटा नहीं है, लेकिन यह एक एकल अभिव्यक्ति है, जो एक बड़ा अंतर बनाता है।
माइकलसनडेन

5
List result = new ArrayList();
while (i.hasNext()){
    result.add(i.next());
}

11
@LuggiMendoza: स्टैक ओवरफ्लो का मतलब ऐसी जगह नहीं है जहां आप बस अपनी समस्या को काट और पेस्ट कर सकते हैं। यह जानकारीपूर्ण होने के लिए है। यह एक पूरी तरह से जानकारीपूर्ण उत्तर है और किसी भी उचित व्यक्ति को इसे एक साथ रखने में सक्षम होना चाहिए कि मैं एक पुनरावृत्त था। वहां की ध्वनियों से, आप यह समझने की कोशिश में लगभग कोई प्रयास नहीं करते हैं कि क्या चल रहा था।
CaTalyst.X

2

कैक्टसStickyList से कोशिश करें :

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

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


इस सवाल का जवाब नहीं है। Iterable! =Iterator
xehpuk

महान, अब आपको संभवतः नए संस्करण के लिए JavaDoc उत्पन्न करने और लिंक को अपडेट करने की आवश्यकता है। :)
xehpuk

2

यहां धाराओं का उपयोग करते हुए एक-लाइनर है

Iterator<?> iterator = ...
List<?> list = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false)
                .collect(Collectors.toList());

1

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

सूची सूची = Stream.generate (पुनरावृति :: अगला)
    .collect (Collectors.toList ());

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

Xehpuk के उत्तर का उपयोग इसके बजाय किया जाना चाहिए यदि Iterator → स्ट्रीम → सूची तरीका आपकी पसंद है।



-2

यहां इस मामले में अगर आप सबसे तेज तरीका चाहते हैं तो for loopबेहतर है।

लूप के लिए जहां 10,000 runsले जाता है के एक नमूने के आकार पर चलनेवाला40 ms2 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
निश्चित रूप से एक forलूप का उपयोग करना और एक सूची के तत्वों के साथ पहुंच बनाना एक get(i)इट्रेटर का उपयोग करने की तुलना में तेज है ... लेकिन यह वह नहीं है जो ओपी पूछ रहा था, उन्होंने विशेष रूप से उल्लेख किया है कि एक इटरेटर इनपुट के रूप में दिया गया है।
सकर लोपेज

@ ऑस्कर मुझे खेद है। क्या मैं अपना उत्तर हटाऊंगा?
vikiiii

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

मुझे लगता है कि @ thinkscarLópez सही है ... यह आवश्यक उत्तर नहीं हो सकता है, लेकिन इसमें पाठकों के लिए उपयोगी जानकारी शामिल है (जैसे खुद: पी)।
चॉथिक प्रोजेक्ट

आपके उत्तर में एक बग है। में get(int)पाश आप केवल 1 मी प्रविष्टियों की 100k देख रहे हैं। यदि आप उस लूप को बदल देते हैं तो आप it.size()देखेंगे कि ये 2 विधियाँ समान गति के करीब हैं। सामान्य तौर पर इन प्रकार के जावा गति परीक्षण सीमित वास्तविक जीवन प्रदर्शन की जानकारी प्रदान करते हैं और इस पर संदेह की दृष्टि से देखा जाना चाहिए।
ग्रे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.