कन्वर्ट जावा सरणी को Iterable में बदलें


150

मेरे पास आदिम का एक सरणी है, उदाहरण के लिए, int, int [] फू। यह एक छोटे आकार का हो सकता है, या नहीं।

int foo[] = {1,2,3,4,5,6,7,8,9,0};

इससे बनाने का सबसे अच्छा तरीका क्या है Iterable<Integer>?

Iterable<Integer> fooBar = convert(foo);

टिप्पणियाँ:

कृपया लूप का उपयोग करके जवाब न दें (जब तक कि आप इस बारे में अच्छी व्याख्या नहीं दे सकते कि कंपाइलर उनके बारे में कुछ स्मार्ट कैसे करते हैं?)

उस पर भी ध्यान दें

int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);

संकलन भी नहीं करेंगे

Type mismatch: cannot convert from List<int[]> to List<Integer>

यह भी जांचें कि एक सरणी Iterable के लिए असाइन करने योग्य क्यों नहीं है? उत्तर देने से पहले।

इसके अलावा, यदि आप कुछ पुस्तकालय (जैसे, अमरूद) का उपयोग करते हैं, तो कृपया बताएं कि यह सबसे अच्छा क्यों है। (क्योंकि इसका Google से पूर्ण उत्तर नहीं है: P)

अंतिम, चूंकि उस बारे में एक होमवर्क लगता है, होमवर्क कोड को पोस्ट करने से बचें।



उन्हें एक लिंक्डलिस्ट में जोड़ें, फिर उस सेट के पुनरावृत्तिकर्ता को वापस करें।

जवाबों:


117
Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

List<Integer> list = Arrays.asList(foo);
// or
Iterable<Integer> iterable = Arrays.asList(foo);

हालांकि इसके लिए आपको काम करने के लिए एक Integerसरणी (एक intसरणी नहीं ) का उपयोग करने की आवश्यकता है ।

आदिम के लिए, आप अमरूद का उपयोग कर सकते हैं:

Iterable<Integer> fooBar = Ints.asList(foo);
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>15.0</version>
    <type>jar</type>
</dependency>

Java8 के लिए: (जिन क्वॉन के उत्तर से)

final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();

10
दो नोट: 1) उसके पास है int, Integer2 नहीं ) Listपहले से ही Iterableतीसरी लाइन बेकार है।
maksimov

1
उसे Iterable की आवश्यकता है कि तीसरी पंक्ति क्यों है।
fmucar

5
दूसरी और तीसरी पंक्तियाँ विकल्प हैं जो मैं कहूंगा :)
fmucar

1
यह एक होमवर्क का हिस्सा नहीं है, मैं सिर्फ एक सरणी या सूची की सामग्री को संसाधित करने वाले डिबगिंग फ़ंक्शन के लिए डुप्लिकेटिंग कोड से बचने की कोशिश कर रहा था ... जब मैं चारों ओर देख रहा था तो मुझे वास्तव में Arrays.asList (..) मिल गया था; लेकिन कम से कम ग्रहण लगता है कि यह वह नहीं करेगा जो मैं चाहता हूं (उदाहरण के लिए, यह Arrays.asList (foo) के परिणाम को एक सूची <int []>, नहीं सूची <Integer> ...) के रूप में प्रभावित करता है। मुझे यह दिलचस्प पर्याप्त के लिए मिला प्रश्न ... (सीमाओं के कारणों में -बड़ी टिप्पणी)
ntg

1
सामान्य तौर पर कोई भी इसे करने के बहुत से तरीकों के बारे में सोच सकता था, लेकिन मैं सोच रहा था कि सबसे अच्छा क्या है (उदाहरण के लिए एक लूप imho होगा जो धीमी की तुलना में ... {ठीक है, समस्या यह है कि मैं कुछ भी नहीं सोच सकता !: )}) इसके अलावा एक चर्चा के लिए stackoverflow.com/questions/1160081/… क्यों, मेरा सवाल हालांकि क्यों नहीं है, लेकिन कैसे, और किस प्रकार का कंटेनर सबसे अच्छा होगा (क्यों ArrayList? वास्तव में, मैं कुछ अमूर्तवादी की कल्पना कर सकता हूं जेनेरिक का उपयोग कर रैपर .., संभवतः आकार पर निर्भर करता है ...)
एनटीजी

44

सिर्फ मेरे 2 सेंट:

final int a[] = {1,2,3};

java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() {

    public Iterator<Integer> iterator() {
       return new Iterator<Integer>() {
            private int pos=0;

            public boolean hasNext() {
               return a.length>pos;
            }

            public Integer next() {
               return a[pos++];
            }

            public void remove() {
                throw new UnsupportedOperationException("Cannot remove an element of an array.");
            }
        };
    }
};

9
निकालें () जावा 8 में neccessary नहीं है, क्योंकि यह एक डिफ़ॉल्ट विधि है जो UnsupportedOperationException को फेंकता है। यदि आप एक बेहतर स्पष्टीकरण संदेश देना चाहते हैं।
एलेक्स

+1 मैं Iterator<Character>a से बनाने के लिए कुछ समान करता हूं String। अपने खुद के लागू करने Iteratorबेकार में सभी मान के माध्यम से पुनरावृत्ति आदिम प्रकार के लिए ऑब्जेक्ट प्रकार से परिवर्तित करने के लिए (अमरूद के माध्यम से बचने के लिए एक ही रास्ता की तरह लगता है Ints.asList(), उदाहरण के लिए) सिर्फ एक पाने के लिए सक्षम होने के लिए Iteratorसे Listबनाया गया था कि।
स्पाकार्की

2
आप सही हैं एलेक्स। डिफ़ॉल्ट तरीके जावा 8 में जोड़े गए थे। 2013 में मैंने यहां इस प्राचीन टुकड़े को जोड़ा।
जोर्ज रुएथसिलिंगिंग

29

जावा 8 के साथ, आप ऐसा कर सकते हैं।

final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();

20

अमरूद आपको वह एडाप्टर प्रदान करता है जिसे आप Int.asList () के रूप में चाहते हैं । संबंधित वर्ग में प्रत्येक आदिम प्रकार के लिए एक समान है, जैसे, के Booleansलिए boolean, आदि।

int foo[] = {1,2,3,4,5,6,7,8,9,0};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
    System.out.println(i);
}

उपयोग करने के लिए ऊपर दिए गए सुझाव Arrays.asListकाम नहीं करेंगे, भले ही वे संकलन करें क्योंकि आपको Iterator<int[]>इसके बजाय मिलता है Iterator<Integer>। क्या होता है कि आपके सरणी द्वारा समर्थित सूची बनाने के बजाय, आपने सरणी का 1-तत्व सूची बनाया है, जिसमें आपका सरणी है।


बस एक नोट: लिंक अब काम नहीं कर रहा है। Github लिंक: github.com/google/guava/blob/master/guava/src/com/google/common/…
१45

थैंक्स @Passi, फिक्स्ड (अब javadoc से लिंक करने के लिए एक Google समर्थित तरीका नहीं मिल सकता है, इसलिए मैं दिए गए स्रोत से जुड़ा हुआ हूं)।
BeeOnRope

8

मेरे पास एक ही समस्या थी और इसे इस तरह हल किया:

final YourType[] yourArray = ...;
return new Iterable<YourType>() {
  public Iterator<YourType> iterator() {
     return Iterators.forArray(yourArray);   // Iterators is a Google guava utility
  }
}

पुनरावृत्ति करने वाला खुद एक आलसी है UnmodifiableIteratorलेकिन मुझे वही चाहिए जो मुझे चाहिए था।


7

जावा 8 या उसके बाद में, Iterableएक कार्यात्मक इंटरफ़ेस रिटर्न है Iterator। तो आप ऐसा कर सकते हैं।

int[] array = {1, 2, 3};
Iterable<Integer> iterable = () -> Arrays.stream(array).iterator();
for (int i : iterable)
    System.out.println(i);

->

1
2
3

3

सबसे पहले, मैं केवल इस बात Arrays.asList(T...)से सहमत हो सकता हूं कि स्पष्ट रूप से नॉन-प्राइमेट डेटाैटिप्स के साथ रैपर प्रकार या सरणियों के लिए सबसे अच्छा समाधान है। यह विधि कक्षा AbstractListमें एक साधारण निजी स्थैतिक कार्यान्वयन के एक निर्माता को बुलाती है Arraysजो मूल रूप से दिए गए सरणी संदर्भ को फ़ील्ड के रूप में सहेजता है और आवश्यक विधियों को ओवरराइड करके सूची का अनुकरण करता है।

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

1) आप प्रत्येक आदिम डेटाप्रकार सरणी (के लिए एक स्थिर विधि के साथ एक वर्ग बना सकते हैं boolean, byte, short, int, long, char, float, doubleएक लौटने Iterable<WrapperType >इन विधियों की अनाम कक्षाओं का प्रयोग करेंगे। Iteratorइसके अलावा (Iterable) जिसमें int[]विधियों को लागू करने के लिए क्षेत्र के तर्क के उदाहरण (उदाहरण के लिए ) को फ़ील्ड के रूप में शामिल करने की अनुमति है।

-> यह दृष्टिकोण प्रदर्शन योग्य है और आपको मेमोरी बचाता है (नए बनाए गए तरीकों की स्मृति को छोड़कर, भले ही, Arrays.asList()उसी तरह से मेमोरी का उपयोग करना होगा)

2) चूंकि सरणियों में विधियां नहीं होती हैं (जैसा कि पक्ष में पढ़ा जा सकता है) आप जुड़े) वे Iteratorया तो एक उदाहरण प्रदान नहीं कर सकते । यदि आप वास्तव में नई कक्षाएं लिखने के लिए बहुत आलसी हैं, तो आपको पहले से मौजूद वर्ग के एक उदाहरण का उपयोग करना होगा जो लागू करता है Iterableक्योंकि तत्काल Iterableया उपप्रकार के अलावा कोई अन्य तरीका नहीं है ।
मौजूदा संग्रह व्युत्पन्न कार्यान्वयन बनाने का एकमात्र तरीका हैIterableएक लूप का उपयोग करना है (सिवाय इसके कि आप अनाम वर्गों का उपयोग करें जैसा कि ऊपर वर्णित है) या आप एक Iterableक्रियान्वयन वर्ग को रोकते हैं जिसका निर्माता एक आदिम प्रकार के सरणी की अनुमति देता है (क्योंकि Object[]आदिम प्रकार के तत्वों के साथ सरणियों की अनुमति नहीं है) लेकिन जहां तक ​​मुझे पता है, जावा एपीआई उस तरह एक वर्ग की सुविधा नहीं है।

लूप का कारण आसानी से समझाया जा सकता है:
प्रत्येक संग्रह के लिए आपको वस्तुओं की आवश्यकता होती है और आदिम डेटाटाइप्स ऑब्जेक्ट नहीं हैं। ऑब्जेक्ट्स आदिम प्रकारों की तुलना में बहुत बड़े होते हैं ताकि उन्हें अतिरिक्त डेटा की आवश्यकता हो जो कि प्रत्येक प्रकार के आदिम प्रकार के सरणी के लिए उत्पन्न होने चाहिए। इसका मतलब है कि अगर तीन तरीकों के दो तरीकों ( Arrays.asList(T...)मौजूदा संग्रह का उपयोग करना या उपयोग करना) के लिए ऑब्जेक्ट्स के कुल की आवश्यकता होती है, तो आपको अपने प्रत्येक प्राइमरी वैल्यू के लिए निर्माण करना होगाint[]रैपर ऑब्जेक्ट को सरणी। तीसरा तरीका सरणी का उपयोग करेगा और इसे अनाम वर्ग में उपयोग करेगा क्योंकि मुझे लगता है कि यह तेज प्रदर्शन के कारण बेहतर है। उस पद्धति के लिए तर्क के रूप में

एक तीसरी रणनीति भी है Objectजहां आप सरणी का उपयोग करना चाहते हैं या Iterableइसके लिए टाइप चेक की आवश्यकता होगी कि तर्क किस प्रकार का है, हालांकि मैं इसे बिल्कुल भी अनुशंसित नहीं करूंगा क्योंकि आपको आमतौर पर आवश्यकता होती है विचार करें कि ऑब्जेक्ट हमेशा आवश्यक प्रकार नहीं होता है और आपको कुछ मामलों के लिए अलग कोड की आवश्यकता होती है।

अंत में, यह जावा की समस्याग्रस्त जेनेरिक प्रकार प्रणाली की गलती है जो सामान्य प्रकार के रूप में आदिम प्रकारों का उपयोग करने की अनुमति नहीं देता है जो केवल कोड का उपयोग करके बहुत सारे कोड को बचाएगा।Arrays.asList(T...)। तो आपको प्रत्येक आदिम प्रकार के सरणी के लिए प्रोग्राम करने की आवश्यकता है, आपको आवश्यकता है, ऐसी विधि (जो मूल रूप से C ++ प्रोग्राम द्वारा उपयोग की जाने वाली मेमोरी के लिए कोई अंतर नहीं करती है जो प्रत्येक प्रयुक्त प्रकार तर्क के लिए एक अलग विधि का निर्माण करेगी।


3

आप कैक्टसIterableOf से उपयोग कर सकते हैं :

Iterable<String> names = new IterableOf<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

फिर, आप इसका उपयोग करके सूची में बदल सकते हैं ListOf:

List<String> names = new ListOf<>(
  new IterableOf<>(
    "Scott Fitzgerald", "Fyodor Dostoyevsky"
  )
);

या बस यह:

List<String> names = new ListOf<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

1

जबकि इसी तरह का उत्तर पहले से ही पोस्ट किया गया है, मुझे लगता है कि नए PrimitiveIterator.OfInt का उपयोग करने का कारण स्पष्ट नहीं था। एक अच्छा समाधान यह है कि जावा 8 प्रिमाइटरेटर का उपयोग किया जाए क्योंकि यह आदिम अंतर प्रकारों के लिए विशिष्ट है (और अतिरिक्त बॉक्सिंग / अनबॉक्सिंग दंड से बचा जाता है):

    int[] arr = {1,2,3};
    // If you use Iterator<Integer> here as type then you can't get the actual benefit of being able to use nextInt() later
    PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.nextInt());
        // Use nextInt() instead of next() here to avoid extra boxing penalty
    }

Ref: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html


-2

Java8 में IntSteam स्ट्रीम को Integers के स्ट्रीम में बॉक्स किया जा सकता है।

public static Iterable<Integer> toIterable(int[] ints) {
    return IntStream.of(ints).boxed().collect(Collectors.toList());
}

मुझे लगता है कि सरणी के आकार के आधार पर प्रदर्शन के मामले।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.