जावा 8 JDK का उपयोग करके Iterable को स्ट्रीम में बदलें


418

मेरे पास एक इंटरफ़ेस है जो लौटता है java.lang.Iterable<T>

मैं जावा 8 स्ट्रीम एपीआई का उपयोग करके उस परिणाम में हेरफेर करना चाहूंगा।

हालांकि Iterable "स्ट्रीम" नहीं कर सकता।

किसी भी विचार को सूची में परिवर्तित किए बिना Iterable को एक स्ट्रीम के रूप में कैसे उपयोग किया जाए?


2
यदि आप पुनरावृत्ति कर सकते हैं, तो अपनी स्थिति या मूल्य की जांच करने के लिए एक लूप का उपयोग क्यों नहीं करते?
अफजल अहमद जीशान

26
@AfzaalAhmadZeeshan क्योंकि धाराएँ बहुत बेहतर हैं
स्लीमन जेनिडी

1
जैसा कि मैंने कहा, मुझे उस सूची (फिल्टर, मैपिंग) पर कुछ मैनिपुलेशन करने की आवश्यकता है। मैं नए जावा 8 JDK API -> स्ट्रीम का उपयोग करना चाहूंगा। लेकिन Iterable isnot "SteamAble"
Rayman

अजीब लगता है कि myIterable.stream()मौजूद नहीं है!
जोश एम।

7
@ गिलूम: हाँ, लेकिन Stream.of(iterable)पैदा करता है Stream<Iterable<Object>>
मथायस ब्रॉन

जवाबों:


571

spliteratorUnknownSizeसीधे उपयोग करने से बेहतर उत्तर है , जो आसान है और बेहतर परिणाम देता है। Iterableएक spliterator()विधि है, इसलिए आपको बस अपने स्प्लिटर को प्राप्त करने के लिए उपयोग करना चाहिए। सबसे खराब स्थिति में, यह समान कोड (डिफ़ॉल्ट कार्यान्वयन का उपयोग करता है spliteratorUnknownSize) है, लेकिन अधिक सामान्य मामले में, जहां आपका Iterableपहले से ही एक संग्रह है, आपको बेहतर स्प्लिटर मिलेगा, और इसलिए बेहतर स्ट्रीम प्रदर्शन (शायद यहां तक ​​कि अच्छा समानता)। यह भी कम कोड है:

StreamSupport.stream(iterable.spliterator(), false)
             .filter(...)
             .moreStreamOps(...);

जैसा कि आप देख सकते हैं, एक से एक धारा प्राप्त करना Iterable(यह भी प्रश्न देखें ) बहुत दर्दनाक नहीं है।


109
पर एक स्थिर विधि Streamअच्छा होता, उदा Stream.ofIterable(iterable)
लूट

59
@robinst यह एक चूक नहीं थी; यह एक जानबूझकर (और अत्यधिक बहस वाला) विकल्प था। चुनौती यह है कि यह अस्तित्व में था, इसके साथ आने वाले ट्रेडऑफ को समझने के बिना इसके लिए पहुंचना बहुत आसान होगा। क्योंकि Iterable बहुत सार है, इस तरह की विधि के परिणामस्वरूप सबसे खराब प्रदर्शन संभव हो जाएगा (कोई समानांतर समर्थन, कोई आकार की जानकारी या विशेषताओं (निष्पादन विकल्पों का अनुकूलन करने के लिए उपयोग किया जाता है))। पूरे पारिस्थितिक तंत्र में बेहतर एपीआई में अधिक सोचा परिणाम मजबूर करना। यह "एक्सवाईजेड कोड के लिए सबसे अच्छा क्या है" बनाम "सभी जावा कोड के लिए सबसे अच्छा है।"
ब्रायन गोएट्ज़

2
आपकी व्याख्या के आधार पर, मैं उत्सुक हूं कि हमें Collection.stream () नहीं बल्कि Iterable.stream () मिला। ऐसा लगता है कि Iterable.stream को छोड़ने का तर्क () या (Stream.ofIterable ()) Collection.stream () के लिए समान रूप से लागू होता है।
क्वालीडाफियल


11
@BrianGoetz ऐसा लगता है कि अधिकांश लोग यह समझने के स्तर में नहीं हैं कि आपने ऊपर कहा है या परवाह नहीं है। वे केवल साधारण एपीआई कहकर सरल कोड लिखना चाहते हैं। दूसरी ओर, वे चीजें (समानांतर ...) शायद दैनिक चलने वाले अधिकांश संचालन के लिए महत्वपूर्ण नहीं हैं।
user_3380739

71

यदि आप अमरूद पुस्तकालय का उपयोग कर सकते हैं, तो संस्करण 21 से, आप उपयोग कर सकते हैं

Streams.stream(iterable)

2
या, यदि आप एक पुराने संस्करण पर अटक गए हैं, तो उपयोग करें Lists.newArrayList(Iterable)
जैकब वैन लिंगन

1
वर्तमान अमरूद कार्यान्वयन स्वीकार किए गए उत्तर से भी बदतर नहीं है: github.com/google/guava/blob/master/guava/src/com/google/common/…
Vadzim

23

आप आसानी से या में Streamसे एक बना सकते हैं :IterableIterator

public static <T> Stream<T> stream(Iterable<T> iterable) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            iterable.iterator(),
            Spliterator.ORDERED
        ),
        false
    );
}

2
आपको इस फ़ंक्शन को एक बार लिखना होगा और फिर इसे कॉल करना होगा। stream(...)आपके कोड को अव्यवस्थित करने के लिए कॉल क्यों करता है ?
gexicide

1
इसे कम और सुरुचिपूर्ण करना चाहते थे .. आप सही है कि मैं इस फ़ंक्शन को एक बार लिख सकता हूं .. लेकिन मैं ड्रॉपिंग कोड में हूं (और जोड़ नहीं रहा हूं)। वैसे भी यह उत्तर सही है क्योंकि इसे परिवर्तित करने का तरीका है।
रेमन

स्थिर आयात समारोह कहा। छोटा और सुरुचिपूर्ण। (हालांकि जरूरी नहीं कि पारदर्शी हो)
aepurniet

9

मैं जोल लाइब्रेरी का उपयोग करने का सुझाव देना चाहता हूं , यह Seq.seq (iterable) कॉल के पीछे स्प्लिटर मैजिक छुपाता है और अतिरिक्त उपयोगी कार्यक्षमता का एक पूरा गुच्छा भी प्रदान करता है।


7

इसलिए एक अन्य जवाब के रूप में अमरूद का उपयोग करके इसके लिए समर्थन का उल्लेख किया गया है:

Streams.stream(iterable);

मैं इस बात पर प्रकाश डालना चाहता हूं कि कार्यान्वयन सुझाए गए अन्य उत्तरों की तुलना में कुछ अलग करता है। यदि Iterableप्रकार का है, तो Collectionवे इसे डालते हैं।

public static <T> Stream<T> stream(Iterable<T> iterable) {
  return (iterable instanceof Collection)
    ? ((Collection<T>) iterable).stream()
    : StreamSupport.stream(iterable.spliterator(), false);
}

public static <T> Stream<T> stream(Iterator<T> iterator) {
  return StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(iterator, 0),
    false
  );
}

5

मैंने यह वर्ग बनाया है:

public class Streams {
    /**
     * Converts Iterable to stream
     */
    public static <T> Stream<T>  streamOf(final Iterable<T> iterable) {
        return toStream(iterable, false);
    }

    /**
     * Converts Iterable to parallel stream
     */
    public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) {
        return toStream(iterable, true);
    }

    private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) {
        return StreamSupport.stream(iterable.spliterator(), isParallel);
    }
}

मुझे लगता है कि यह पूरी तरह से पठनीय है क्योंकि आपको spliterators और बुलियन (isParallel) के बारे में सोचने की ज़रूरत नहीं है।


4

इस मुद्दे के लिए एक बहुत ही सरल काम है, एक ऐसा Streamable<T>इंटरफ़ेस बनाना है Iterable<T>जो एक default <T> stream()विधि रखता हो ।

interface Streamable<T> extends Iterable<T> {
    default Stream<T> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

अब आप में से किसी को भी इसके बजाय Iterable<T>केवल घोषित करके तुच्छ बना दिया जा सकता implements Streamable<T>है Iterable<T>



-1

यह करने के लिए एक और तरीका है, जावा 8 के साथ और बाहरी देयता के बिना:

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