संग्रह को सरणी में बदलने का सबसे आसान तरीका?


125

मान लीजिए कि हमारे पास ए Collection<Foo>। इसे बदलने के लिए एलओसी (वर्तमान संदर्भ में सबसे छोटा) क्या है Foo[]? किसी भी प्रसिद्ध पुस्तकालय की अनुमति है।

युपीडी:;: क्या बदलने के बारे में (इस भाग में एक और मामला छुट्टी टिप्पणियां यदि आप इसे की कीमत इसके लिए एक और धागा बनाने के लिए लगता है) Collection<Foo>करने के लिए Bar[]जहां Barप्रकार के 1 पैरामीटर के साथ निर्माता है Fooयानी public Bar(Foo foo){ ... }?


इसी तरह के प्रदर्शन और इसके साथ स्पष्टीकरण के साथ एक ही ऑपरेशन करने के लिए JDK-11 में पेश किए गए वैकल्पिक एपीआई के साथ यह जवाब दिया। प्लस सिंटैक्स Stream.toArrayJDK से मौजूदा एपीआई से मेल खाता है ।
नमन

जवाबों:


256

xसंग्रह कहां है:

Foo[] foos = x.toArray(new Foo[x.size()]);

35
सरल (आसान) लेकिन सर्वोत्तम नहीं (मेमोरी): x.toArray(new Foo[0]) --- प्रलेखन : पढ़ने का समय नहीं ...
user85421

6
@ कार्लोस वास्तव में, इससे बेहतर मेमोरी का उपयोग करता है (new Foo[0])। Collection.toArray प्रलेखन के अनुसार, '@ अपरम वह सरणी है जिसमें इस संग्रह के तत्वों को संग्रहीत किया जाना है, यदि यह पर्याप्त रूप से बड़ा है' जिसका अर्थ है कि यह उन्हें सीधे उस नए सरणी में संग्रहीत करेगा। यदि आप इसे 0 आकार देते हैं, तो यह एक नया सरणी बना देगा, जिसका अर्थ है कि आपके पास एक छोटा सा सरणी है और ऐसा अनावश्यक होने पर एक बड़ा सरणी बनाया जा सकता है।
corsiKa

4
@glowcoder - लेकिन इसे कम से कम किया जा सकता है यदि आप एक स्थिर सरणी को एक स्थिर स्थिरांक के रूप में परिभाषित करते हैं। यह toArrayसही प्रकार का एक लक्ष्य सरणी बनाने के लिए सिर्फ एक संकेत है । और इस मामले में, ईमानदारी से, मैं अपने आवेदन में एक अतिरिक्त एकल खाली सरणी की परवाह नहीं करूंगा। यह शोर के स्तर से काफी नीचे है।
एंड्रियास डॉक

2
@glowcoder - यही कारण है कि मैंने ( कोशिश की ) ने लिखा कि उपयोग new Foo[0]करना सरल है "लेकिन सबसे अच्छा नहीं (स्मृति)" ... अर्थात, मेरा मतलब था कि मेरा समाधान आसान है लेकिन सबसे अच्छा नहीं है (यही कारण है कि मैंने इस्तेमाल किया :)।
user85421

21
ध्यान दें कि यह कोड थ्रेडसेफ़ नहीं है, भले ही आप सिंक्रनाइज़ संग्रह का उपयोग कर रहे हों। यह अधिकांश स्थितियों में खुद को व्यवहार में लाएगा, लेकिन अगर x.size () और x.toArray () कॉल के बीच कोई आइटम हटा दिया जाता है, तो परिणामी सरणी में अंत में एक अतिरिक्त अशक्त तत्व होगा। new Foo[0]संस्करण कार्लोस द्वारा प्रस्तावित इस समस्या को कष्ट नहीं होता है।
जूल्स

36

जावा 8 का उपयोग कर अद्यतन प्रश्न का वैकल्पिक समाधान:

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);

35
इसे छोटा किया जा सकता है Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);
lpandzic

सिंटेक्स वार मैं स्वीकृत उत्तर को ज्यादा पसंद करूंगा। काश लोग सब पाइथन पर स्विच कर सकें।
एरिक चेन

@EricChen Python पर स्विच करें - जावा से एक व्याख्या और गतिशील रूप से टाइप की गई भाषा - कोडिंग सिंटैक्स और संख्या रेखाओं के कारण 'संकलित और सांख्यिकीय रूप से टाइप की गई भाषा' भिन्न होती है? अच्छा विचार नहीं।
रफीअल्हमद

10

यदि आप इसे एक से अधिक बार या लूप में उपयोग करते हैं, तो आप एक स्थिरांक को परिभाषित कर सकते हैं

public static final Foo[] FOO = new Foo[]{};

और रूपांतरण इसे पसंद करें

Foo[] foos = fooCollection.toArray(FOO);

toArrayविधि खाली सरणी ले लक्ष्य सरणी का सही प्रकार का निर्धारण करने के लिए और आप के लिए एक नई सरणी का निर्माण करेगा।


यहाँ अद्यतन के लिए मेरा प्रस्ताव है:

Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos) 
    temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});

1
अप, constजावा नहीं है! public static final Foo[] FOO = {}
user85421

1
यह सार्वजनिक क्यों होगा?
ज़ोल्टन

@ ज़ोल्टन - क्यों नहीं? यह अपरिवर्तनीय है, इसलिए सुरक्षा मुद्दा प्रस्तुत नहीं करता है। यह थोड़ा अव्यवस्थित है, लेकिन अन्य कोड में उपयोगी हो सकता है, इसलिए आमतौर पर हानिरहित है। शायद इन सभी स्थिरांक के साथ एक केंद्रीय वर्ग भी बनाते हैं, और फिर import staticउन्हें प्राप्त करने के लिए उपयोग करते हैं।
जूल्स

@ सरणी का संदर्भ अपरिवर्तनीय है, लेकिन इसकी सामग्री नहीं है। वर्ग के बाहर कोई भी सरणी के तत्वों को स्वतंत्र रूप से बदल सकता है। और दूसरी ओर, अंगूठे के एक नियम के रूप में, मेरा मानना ​​है कि सभी क्षेत्रों को तब तक निजी बना दिया जाना चाहिए जब तक कि उन्हें कक्षा के बाहर की आवश्यकता न हो।
ज़ोल्टन

2
शून्य लंबाई होने के नाते, ऐसी कोई सामग्री नहीं है जिसे बदला जा सकता है
जूल्स

5

JDK / 11 के साथ, ए Collection<Foo>को परिवर्तित करने का एक वैकल्पिक तरीका निम्नानुसार Foo[]हो सकता है Collection.toArray(IntFunction<T[]> generator):

Foo[] foos = fooCollection.toArray(new Foo[0]); // before JDK 11
Foo[] updatedFoos = fooCollection.toArray(Foo[]::new); // after JDK 11

जैसा कि @Stuart द्वारा मेलिंग सूची (जोर मेरा) पर समझाया गया है , इसका प्रदर्शन अनिवार्य रूप से मौजूदा के समान होना चाहिएCollection.toArray(new T[0]) -

अपशॉट यह है कि उपयोग करने वाले कार्यान्वयन Arrays.copyOf() सबसे तेज़ हैं, शायद इसलिए कि यह एक आंतरिक है

यह ताजा आवंटित सरणी को शून्य-भरने से बचा सकता है क्योंकि यह जानता है कि संपूर्ण सरणी सामग्री ओवरराइट हो जाएगी। सार्वजनिक API जैसा दिखता है, यह परवाह किए बिना सच है।

JDK के भीतर एपीआई का कार्यान्वयन पढ़ता है:

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

डिफ़ॉल्ट कार्यान्वयन generator.apply(0)शून्य-लंबाई सरणी प्राप्त करने के लिए कॉल करता है और फिर बस कॉल करता है toArray(T[])। यह Arrays.copyOf() तेजी से रास्ते से गुजरता है , इसलिए यह अनिवार्य रूप से उसी गति के समान है toArray(new T[0])


नोट : - बस जब API का उपयोग एक पिछड़ी असंगतता के साथ किया जाएगा जबnullमूल्योंके साथ कोड के लिए उपयोग किया जाता हैजैसेtoArray(null)कि ये कॉल अब मौजूदा के कारण अस्पष्ट होtoArray(T[] a)जाएगा और संकलन करने में विफल होगा।



3

मूल के लिए डबलप जवाब देखें :

Foo[] a = x.toArray(new Foo[x.size()]);

अद्यतन के लिए:

int i = 0;
Bar[] bars = new Bar[fooCollection.size()];
for( Foo foo : fooCollection ) { // where fooCollection is Collection<Foo>
    bars[i++] = new Bar(foo);
}    

3

अपडेट सेक्शन में (Google संग्रह की सहायता से) केस का अंतिम समाधान यहां दिया गया है:

Collections2.transform (fooCollection, new Function<Foo, Bar>() {
    public Bar apply (Foo foo) {
        return new Bar (foo);
    }
}).toArray (new Bar[fooCollection.size()]);

लेकिन, यहां मुख्य दृष्टिकोण का दोहराव के उत्तर में उल्लेख किया गया था (मैं toArrayविधि के लिए भूल गया )।


1
थ्रेड सेफ्टी के बारे में डबलप के जवाब पर मेरी टिप्पणी देखें, जो इस समाधान पर भी लागू होती है। new Bar[0]मुद्दे से बचता है।
जूल्स

-1

उदाहरण के लिए, आपके पास तत्वों के साथ ArrayList संग्रह है छात्र वर्ग:

List stuList = new ArrayList();
Student s1 = new Student("Raju");
Student s2 = new Student("Harish");
stuList.add(s1);
stuList.add(s2);
//now you can convert this collection stuList to Array like this
Object[] stuArr = stuList.toArray();           // <----- toArray() function will convert collection to array
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.