जावा में एक Iterable का आकार प्राप्त करें


88

मुझे Iterableजावा में तत्वों की संख्या का पता लगाने की आवश्यकता है । मैं जानता हूँ मैं यह कर सकता हूँ:

Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
  it.next();
  sum++;
}

मैं भी कुछ इस तरह से कर सकता था, क्योंकि मुझे किसी भी तरह से इटरटेबल में वस्तुओं की आवश्यकता नहीं है:

it = values.iterator();
while (it.hasNext()) {
  it.remove();
  sum++;
}

एक छोटे पैमाने के बेंचमार्क ने इस समस्या के लिए बहुत अधिक प्रदर्शन अंतर, कोई टिप्पणी या अन्य विचार नहीं दिखाए?


क्यों? या तो एक बहुत बुरा विचार है, क्योंकि दोनों ओ (एन) हैं। आपको दो बार संग्रह को पुनरावृत्त करने से बचने की कोशिश करनी चाहिए।
लोर्ने

3
आपके दूसरे को भी काम नहीं करना चाहिए। आप पहले से कॉल remove()किए बिना कॉल नहीं कर सकते next()
लुई वासरमैन

जवाबों:


122

टीएल; डीआर: Iterables.size(Iterable)महान अमरूद पुस्तकालय की उपयोगिता पद्धति का उपयोग करें ।

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

प्रदर्शन के लिए, यह आपकी डेटा संरचना पर निर्भर करता है। यदि यह वास्तव में उदाहरण के लिए है ArrayList, तो शुरुआत से ही तत्वों को हटाना (आपकी दूसरी विधि क्या कर रही है) बहुत धीमी है (आकार की गणना O (n * n) के बजाय O (n) के रूप में की जानी चाहिए)।

सामान्य तौर पर, अगर ऐसा मौका है valuesजो वास्तव में ए Collectionऔर न केवल ए है Iterable, तो इसे जांचें और size()मामले में कॉल करें :

if (values instanceof Collection<?>) {
  return ((Collection<?>)values).size();
}
// use Iterator here...

करने के लिए कॉल size()इच्छा आमतौर पर बहुत तेजी से तत्वों की संख्या की गणना की तुलना में हो सकता है, और इस चाल वास्तव में क्या है Iterables.size(Iterable)के अमरूद आप के लिए करता है।


उनका कहना है कि उन्हें तत्वों में कोई दिलचस्पी नहीं है और अगर उन्हें हटा दिया जाता है तो उन्हें कोई परवाह नहीं है।
ऐयोबे

छोटे स्पष्टीकरण: यह तत्व निकाल देंगे सेvalues
Miquel

1
लेकिन कोड के अन्य भाग अभी भी समान Iterable का उपयोग कर सकते हैं। और अभी नहीं तो शायद भविष्य में।
फिलिप वेंडलर

मैं सुझाव देता हूं कि Google अमरूद के उत्तर को अधिक प्रमुख बनाएं। लोगों के इस कोड को फिर से लिखने का कोई कारण नहीं है, भले ही यह तुच्छ हो।
स्टीफन हैरिसन

8
यदि आप जावा 8 का उपयोग करते हैं, तो एक स्ट्रीम बनाएं और उसमें तत्व की गणना करें: Stream.of (myIterable) .count ()
FrankBr

41

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

Iterable values = ...
long size = values.spliterator().getExactSizeIfKnown();

यह केवल तभी काम करेगा जब iterable source का निर्धारित आकार हो। संग्रह के लिए सबसे Spliterators, लेकिन आप मुद्दों अगर यह एक से आता है हो सकता है जाएगा HashSetया ResultSetउदाहरण के लिए।

आप यहां जावदोक की जांच कर सकते हैं।

यदि जावा 8 कोई विकल्प नहीं है , या यदि आप नहीं जानते कि यह कहां से आता है, तो आप अमरूद के समान ही उपयोग कर सकते हैं:

  if (iterable instanceof Collection) {
        return ((Collection<?>) iterable).size();
    } else {
        int count = 0;
        Iterator iterator = iterable.iterator();
        while(iterator.hasNext()) {
            iterator.next();
            count++;
        }
        return count;
    }

1
कोई, इस आदमी को एक पदक सौंप दो।
प्रमेश बजराचार्य

यह मेरे लिए सॉर्ट के लिए काम नहीं करता है । न्यू बी द्वारा जवाब मेरे लिए काम करता है।
साबिर खान

18

यह शायद थोड़ा देर से है, लेकिन किसी की मदद कर सकता है। मैं Iterableअपने कोडबेस के साथ इसी तरह के मुद्दे पर आता हूं और समाधान for eachस्पष्ट रूप से कॉल किए बिना उपयोग करना था values.iterator();

int size = 0;
for(T value : values) {
   size++;
}

2
यह मेरे लिए एक सहज दृष्टिकोण है, जिसकी मैं सराहना कर सकता हूं। बस कुछ मिनट पहले इसका इस्तेमाल किया। धन्यवाद।
मैट क्रेमेंस

2
हां यह सहज है, लेकिन दुख की बात है कि आपको मूल्य के लिए एक अप्रयुक्त-चेतावनी को दबा देना होगा ...
नील-ओ-चटाई

इस समाधान के लिए धन्यवाद, यह वास्तव में वस्तु का आकार लौटाता है। एकमात्र बैकसाइड यह है कि यदि आप उसी ऑब्जेक्ट के माध्यम से बाद में फिर से पुनरावृति करना चाहते हैं, तो पहले आपको इसे किसी तरह रीसेट करना चाहिए।
जसोलती

7

आप एक सूची में अपने चलने योग्य डाल सकते हैं तो उस पर .size () का उपयोग करें।

Lists.newArrayList(iterable).size();

स्पष्टता के लिए, उपरोक्त विधि के लिए निम्न आयात की आवश्यकता होगी:

import com.google.common.collect.Lists;

2
सूची एक अमरूद वर्ग है
पॉल जैक्सन

6

सख्ती से बोलना, Iterable का आकार नहीं है। एक चक्र की तरह डेटा संरचना पर विचार करें।

और Iterable उदाहरण का अनुसरण करने के बारे में सोचें, कोई आकार नहीं:

    new Iterable(){

        @Override public Iterator iterator() {
            return new Iterator(){

                @Override
                public boolean hasNext() {
                    return isExternalSystemAvailble();
                }

                @Override
                public Object next() {
                    return fetchDataFromExternalSystem();
                }};
        }};

2

मैं it.next()उस सरल कारण के लिए जाऊंगा next()जिसे लागू करने की गारंटी है, जबकि remove()एक वैकल्पिक ऑपरेशन है।

E next()

अगले तत्व को पुनरावृति में देता है।

void remove()

अंतर्निहित संग्रह से हटाता है अंतिम तत्व पुनरावृत्ति (वैकल्पिक संचालन) द्वारा लौटाया जाता है ।


जबकि यह उत्तर तकनीकी रूप से सही है, यह काफी भ्रामक है। कॉलिंग removeको पहले से ही एक के तत्वों को गिनने के गलत तरीके के रूप में नोट किया गया है Iterator, इसलिए यह वास्तव में कोई फर्क नहीं पड़ता कि हम जिस चीज को करने जा रहे हैं वह लागू नहीं है या नहीं।
स्टीफन हैरिसन 19

1
वास्तव में उत्तर का कौन सा हिस्सा भ्रामक है? और जिस परिस्थिति में remove इसे लागू किया जाता है, उसका उपयोग करना गलत क्यों होगा? Btw, डाउनवोट्स गलत उत्तरों या उत्तरों के लिए उपयोग किए जाने वाले टाइपिकॉल्ट हैं जो बुरी सलाह देते हैं। मैं यह नहीं देख सकता कि यह उत्तर उसमें से किसी के लिए कैसे योग्य है।
एरियोब


0

मेरे लिए, ये सिर्फ अलग तरीके हैं। पहला वाला उस वस्तु को छोड़ देता है जिस पर आप अपरिवर्तित रहते हैं, जबकि सेकंड इसे खाली छोड़ देता है। सवाल यह है कि आप क्या करना चाहते हैं। हटाने की जटिलता आपके चलने योग्य वस्तु के कार्यान्वयन पर आधारित है। यदि आप संग्रह का उपयोग कर रहे हैं - जैसे काज़ेक गारा द्वारा प्रस्तावित किया गया था, तो आकार प्राप्त करें - इसका आमतौर पर सबसे अच्छा दृष्टिकोण प्रदर्शन है।


-2

आप तत्वों की संख्या प्राप्त करने के लिए बस size()अपने तरीके का उपयोग क्यों नहीं करते Collectionहैं?

Iterator इसका मतलब केवल पुनरावृति करना है, और कुछ नहीं।


4
कौन कहता है कि वह एक संग्रह का उपयोग कर रहा है? :-)
aioobe

आप एक पुनरावृत्त का उपयोग कर रहे हैं, जो तत्वों को हटाने का समर्थन करता है। यदि आप पुनरावृत्त लूप दर्ज करने से पहले आकार उठाते हैं, तो आपको अपने निष्कासन से सावधान रहने और तदनुसार मूल्य को अपडेट करने की आवश्यकता है।
मिकेल

1
उसका आकार देखने के लिए एक संग्रह क्यों नहीं हो सकता है, इसका एक उदाहरण: वह एक तृतीय-पक्ष एपीआई विधि कह सकता है जो केवल एक Iterable देता है।
21

2
इस उत्तर confuses Iteratorऔर Iterable। सही तरीके के लिए मतदान जवाब देखें।
स्टीफन हैरिसन

-4

लूप का उपयोग करने और प्रत्येक तत्व या गिनती और तीसरे पक्ष के पुस्तकालय का उपयोग करने के बजाय हम केवल ArrayList में चलने योग्य टाइप कर सकते हैं और अपना आकार प्राप्त कर सकते हैं।

((ArrayList) iterable).size();

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