2012-04-26 58 views
90

में कनवर्ट करें मेरे पास प्राइमेटिव्स का ऐरे है, उदाहरण के लिए int, int [] foo। यह एक छोटा आकार का हो सकता है, या नहीं।जावा ऐरे को Iterable

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> 
संकलित नहीं करेगा

उत्तर देने से पहले Why is an array not assignable to Iterable? भी देखें।

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

आखिरकार, ऐसा लगता है कि होमवर्क काम कोड से बचने के लिए।

+0

के संभावित डुप्लिकेट [सरणी के लिए इटरेटर] (http://stackoverflow.com/questions/3912765/iterator-for-array) – NPE

+0

उन्हें एक लिंक्डलिस्ट में जोड़ें, फिर बस उस सेट के इटरेटर को वापस कर दें। –

उत्तर

77
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> 
+7

दो नोट्स: 1) उसके पास 'int' है, न कि 'इंटेगर' 2) 'सूची' पहले से ही' Iterable' है, इसलिए तीसरी पंक्ति व्यर्थ है। – maksimov

+1

उसे इटेबल की जरूरत है कि तीसरी पंक्ति क्यों है। – fmucar

+1

तो दूसरी पंक्ति तब व्यर्थ है? ;) – maksimov

33

सिर्फ मेरी 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."); 
      } 
     }; 
    } 
}; 
+4

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

+0

+1 मैं 'स्ट्रिंग' से 'Iterator ' बनाने के समान कुछ करता हूं। अपने स्वयं के 'इटरेटर' को कार्यान्वित करना ऑब्जेक्ट प्रकार से आदिम प्रकार में परिवर्तित करने के लिए सभी मूल्यों के माध्यम से अनिवार्य रूप से पुनरावृत्ति से बचने का एकमात्र तरीका है (उदाहरण के लिए गुवा के 'इन्ट्स.सलिस्ट()' के माध्यम से), बस प्राप्त करने में सक्षम होने के लिए बनाई गई 'सूची' से 'Iterator'' बनाया गया था। – spaaarky21

+1

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

19

अमरूद अनुकूलक आप Int.asList() के रूप में चाहते हैं प्रदान करता है। वहाँ ऊपर दिए गए सुझाव का उपयोग करने के Arrays.asList काम नहीं करेगा जुड़े कक्षा में प्रत्येक आदिम प्रकार, जैसे, boolean के लिए Booleans, आदि

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); 
} 

के लिए एक समान है, भले ही वे संकलन क्योंकि आप एक Iterator<int[]> बजाय मिल Iterator<Integer>। क्या होता है कि आपके सरणी द्वारा समर्थित सूची बनाने के बजाय, आपने अपनी सरणी वाली एरे की एक 1-तत्व सूची बनाई है।

8

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

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

इटरेटर अपने आप में एक आलसी UnmodifiableIterator है, लेकिन है कि मैं वास्तव में क्या जरूरत है।

3

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

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

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

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

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

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

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

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

20

जावा 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(); 
-1

java8 IntSteam धारा में पूर्णांकों की स्ट्रीम करने के लिए बॉक्सिंग जा सकता है।

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

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

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

, आप एक सूची में बदल सकते हैं:

4

आप IterableOfCactoos से उपयोग कर सकते हैं

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

या बस इस:

List<String> names = new ListOf<>(
    "Scott Fitzgerald", "Fyodor Dostoyevsky" 
); 
संबंधित मुद्दे