ইটারেটরকে অ্যারেলিস্টে রূপান্তর করুন


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
আমি পাই না। অ্যারেলিস্টটি কীভাবে ফিরে এসেছে, বলুন, পেয়ারা কোনও সাধারণ অ্যারেলিস্টের চেয়ে ভাল? তারা কি আরও কার্যকর উপায়ে এটি করে? এমনকি যদি এটি আরও দক্ষ হয় তবে আপনার প্রকল্পে অতিরিক্ত নির্ভরতা (এবং আরও জটিলতা) যুক্ত করা কি সত্যই মূল্যবান?
CorayThan

10
@ কোডাই কম কোড + পরীক্ষিত পদ্ধতি। যদিও আমি আপনার সাথে একমত হয়েছি কেবল সেই পদ্ধতিটি ব্যবহার করার জন্য আমি কোনও অতিরিক্ত নির্ভরতা যুক্ত করব না। তবে তারপরেও, আমার বেশিরভাগ (বৃহত্তর) প্রকল্পগুলি পেয়ারা বা অ্যাপাচি কমন্স ব্যবহার করে ...
রেনেউদ

4
@ কোরেথান আমার বন্ধুকে ভাগ করুন এবং জয় করুন। কেন এমন একটি পদ্ধতি লিখুন যা ইতিমধ্যে একটি পাঠাগার দ্বারা সরবরাহ করা হয়েছে এবং পরীক্ষা করা হয়েছে? আমরা প্রচুর অ্যাপাচি কমন্স এবং পেয়ারা ব্যবহার করছি, তারা কেবল দুর্দান্ত এবং আপনাকে সময় এবং অর্থ সাশ্রয় করতে সহায়তা করে।
স্টিফান

5
রেনাউড এবং স্টিফানের সাথে সম্মত হন। এছাড়াও, আপনি যদি কোনও বিল্ড টুল ব্যবহার করেন তবে এই লাইব্রেরিগুলি অন্তর্ভুক্ত করা বিশ্বের সবচেয়ে সহজ জিনিস ... এছাড়াও ... যদি আপনি সত্যিই সেগুলি অন্তর্ভুক্ত না করতে চান তবে আপনি অ্যাপাচি / পেয়ারা কোডের উত্সটিতে যেতে পারেন এবং তারা সেখানে কী করেছে তা অনুলিপি করুন: ইতিমধ্যে উপস্থিত শত শত সুন্দর প্রকৌশলী এবং পরীক্ষিত চাকাগুলিকে পুনর্নবীকরণের চেয়ে আপনার সময় নষ্ট করার চেয়ে আরও ভাল।
মাইক রডেন্ট

238

জাভা 8-এ, আপনি ইন্টারফেসে forEachRemainingযুক্ত হওয়া নতুন পদ্ধতিটি ব্যবহার করতে পারেন Iterator:

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

2
মানে কি ::? এর নাম কি? list.add () এর সরাসরি উল্লেখ বলে মনে হচ্ছে; এবং কিছু java8 নতুন জিনিস মনে হয়; এবং ধন্যবাদ! :)
অ্যাকুরিয়াস পাওয়ার

13
@ অ্যাকোয়ারিয়াসপাওয়ার ::জাভা 8- এ সিনট্যাক্সটি নতুন, এবং এটি একটি "পদ্ধতির রেফারেন্স" বোঝায় যা ল্যাম্বদার একটি সংক্ষিপ্ত রূপ। আরও তথ্যের জন্য এখানে দেখুন: docs.oracle.com/javase/tutorial/java/javaOO/…
স্টুয়ার্ট মার্ক

কোথা iteratorথেকে আসছে? এটি একটি অমীমাংসিত প্রতীক
জাভাদবা

1
@ জাভাদবা মূল প্রশ্নটি ছিল আপনার ইতিমধ্যে একটি নতুন অ্যারেলিস্টে রূপান্তরকারীকে কীভাবে রূপান্তর করবেন। এই উদাহরণের উদ্দেশ্যে, আপনার ইতিমধ্যে থাকা পুনরাবৃত্তিকে কল করা হবে বলে ধরে নেওয়া হয় iterator
স্টুয়ার্ট

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত, কারণ এটি সবচেয়ে সংক্ষিপ্ত এবং তৃতীয় পক্ষের লাইব্রেরিতে নির্ভর করে না
ড্যানিয়েলকুয়াদ্রা

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
প্রশ্নটি আইট্রেটরের সম্পর্কে <এলিমিটি> একটি সূচনা পয়েন্ট হিসাবে, আইটেবল <এলিমেন্ট> নয়।
যাপ

1
উপরোক্ত মন্তব্যে একমত বিভ্রান্তিকর যে আপনি আপনার নাম Iterable iterator। এগুলি সম্পূর্ণ আলাদা।
স্টিফেন হ্যারিসন

জাভা 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 টু অ্যারে পদ্ধতিও রয়েছে এবং 1 টি এক ধরণের গ্রহণ করে: commons.apache.org/proper/commons-collections/javadocs/… , java.lang.Class)

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চাপানো এ ক্ষেত্রে পঠনযোগ্যতার উন্নতি করে না, যেহেতু এটি a Streamএবং a দ্বারা সমর্থন করা উচিত Spliterator
শিপি

1
@ সার্জিও এটি সংক্ষিপ্ত নয়, তবে এটি একটি একক প্রকাশ, যা একটি বিশাল পার্থক্য তৈরি করে।
মাইকেলসনডনউডে

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

11
@ লুগিমেডোজা: স্ট্যাক ওভারফ্লো এমন কোনও স্থান নয় যা আপনি কেবল কেটে পেস্ট করতে পারেন এবং আপনার সমস্যার সমাধান করতে পারেন। এটি তথ্যবহুল হতে বোঝানো হয়েছে। এটি একটি সঠিক তথ্যমূলক উত্তর এবং যে কোনও যুক্তিসঙ্গত ব্যক্তিকে এটি একসাথে রাখতে সক্ষম হওয়া উচিত যে আমি একজন পুনরাবৃত্তিকারী। এর শব্দগুলি থেকে, আপনি কী চলছে তা বোঝার চেষ্টা করার জন্য প্রায় কোনও প্রচেষ্টা করেননি।
ক্যাটালিস্ট.এক্স

2

ক্যাকটুসStickyList থেকে চেষ্টা করুন :

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

দাবি অস্বীকার: আমি অন্যতম বিকাশকারী।


এটি প্রশ্নের উত্তর দেয় না। Iterable! =Iterator
xehpuk

দুর্দান্ত, এখন আপনাকে সম্ভবত নতুন সংস্করণটির জন্য জাভাডক তৈরি করতে হবে এবং লিঙ্কটি আপডেট করতে হবে। :)
xehpuk

2

এখানে স্ট্রিম ব্যবহার করে একটি ওয়ান-লাইনার দেওয়া হয়েছে

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

1

আমি কেবল একটি আপাতদৃষ্টিতে সুস্পষ্ট সমাধানটি নির্দেশ করতে চাই যা কার্যকর হবে না :

তালিকা তালিকা = স্ট্রিম.জেনারেট (পুনরুক্তিকারী :: পরের)
    .collect (Collectors.toList ());

এটি কারণ Stream#generate(Supplier<T>)কেবলমাত্র অসীম স্ট্রিম তৈরি করতে পারে, এটি তার যুক্তি নিক্ষেপ করার আশা করে না NoSuchElementException( Iterator#next()এটিই শেষ পর্যন্ত কী করবে)।

Xehpuk এর উত্তর পরিবর্তে ব্যবহার করা উচিত যদি Iterator → স্ট্রিম → তালিকার উপায়টি আপনার পছন্দ হয়।



-2

এখানে এই ক্ষেত্রে আপনি যদি দ্রুততম উপায় চান তবে for loopআরও ভাল।

একটি নমুনা আকার উপর পুনরুক্তিকারীর 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
অবশ্যই একটি forলুপ ব্যবহার করা এবং এর সাথে তালিকার উপাদানগুলিতে অ্যাক্সেস get(i)করা একটি আয়রেটর ব্যবহারের চেয়ে দ্রুততর ... তবে ওপি যা বলছিল তা নয়, তিনি বিশেষভাবে উল্লেখ করেছিলেন যে একটি পুনরুক্তিটিকে ইনপুট হিসাবে দেওয়া হয়।
অস্কার লোপেজ

@ অস্কার আমি দুঃখিত, আমার উত্তর মুছে ফেলা উচিত?
vikiiii

এটাই তোমার ডাক। আমি এটি এখনও মুছে ফেলব না, এটি তথ্যপূর্ণ হতে পারে। আমি কেবল তখন আমার উত্তরগুলি মুছতে হয় যখন লোকেরা তাদের নীচে নামতে শুরু করে :)
এসকর লোপেজ

আমি মনে করি @ ÓscarLópez ঠিক আছে ... এটি প্রয়োজনীয় উত্তর নাও হতে পারে তবে এতে পাঠকদের জন্য দরকারী তথ্য রয়েছে (আমার মতো: পি)।
Chthonic প্রকল্প

আপনার উত্তরে একটি বাগ আছে। ইন get(int)লুপ আপনি শুধুমাত্র 1 মি এন্ট্রির 100 কিলোবাইট এ খুঁজছেন। আপনি যদি সেই লুপটি পরিবর্তন করেন তবে আপনি it.size()দেখতে পাবেন যে এই 2 টি পদ্ধতি একই গতির কাছে রয়েছে। সাধারণভাবে এই ধরণের জাভা স্পিড পরীক্ষাগুলি বাস্তব জীবনের পারফরম্যান্সের সীমাবদ্ধ তথ্য সরবরাহ করে এবং সন্দিহানভাবে দেখা উচিত।
ধূসর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.