2015-02-16 2 views
11

Stream एक इंटरफ़ेस है इसलिए जब भी कोई Stream ऑब्जेक्ट धारण करता है वहां बहुत सारे कार्यान्वयन विशिष्ट विवरण छुपाए जाते हैं।मानक संग्रह द्वारा स्ट्रीम कार्यान्वयन कितने विशेष हैं?

List<String> list = new ArrayList<>(); 
... 
int size = list.stream() 
       .count(); 

यह निरंतर या रैखिक समय में किये है:

उदाहरण के लिए, निम्न कोड ले? या यह:

Set<String> set = new TreeSet<>(); 
... 
set.stream() 
    .sorted() 
    .forEach(System.out::println); 

क्या यह ओ (एन) या ओ (एन लॉग एन) होगा?

सामान्य रूप से, मानक संग्रह द्वारा धाराओं के कार्यान्वयन कितने विशिष्ट हैं?

उत्तर

15

क्या यह स्थिर या रैखिक समय में चलता है?

वर्तमान कार्यान्वयन रैखिक समय में चलता है:

public final long count() { 
    return mapToLong(e -> 1L).sum(); 
} 

लेकिन, इस कुछ स्थितियों में लगातार समय में चलाने के लिए सुधार किया जा सकता (इस कहीं के लिए एक RFE है)।

कैसे? एक धारा एक स्ट्रीम स्रोत, शून्य या अधिक मध्यवर्ती संचालन, और एक टर्मिनल आपरेशन (यहाँ, count() टर्मिनल ऑपरेशन है) द्वारा वर्णित है। धारा कार्यान्वयन स्रोत के बारे में विशेषताओं का एक सेट बनाए रखता है, और जानता है कि संचालन द्वारा विशेषताओं को कैसे संशोधित किया जाता है। उदाहरण के लिए, संग्रह द्वारा समर्थित एक धारा में विशेषता SIZED है, जबकि एक इटरेटर द्वारा समर्थित धारा का आकार नहीं है। इसी तरह, ऑपरेशन map() आकार-संरक्षण है, लेकिन ऑपरेशन filter() किसी भी आकार के किसी भी पूर्व ज्ञान को नष्ट कर देता है। धारा कार्यान्वयन टर्मिनल ऑपरेशन शुरू करने से पहले पाइपलाइन की रचित विशेषताओं को जानता है, इसलिए यह जानता है कि स्रोत आकार का है या नहीं और सभी चरणों आकार-संरक्षण हैं, और ऐसे मामलों में, बस आकार के स्रोत को पूछ सकते हैं और सभी को बाईपास कर सकते हैं वास्तविक धारा गणना। (लेकिन जावा 8 में कार्यान्वयन ऐसा नहीं होता है।)

ध्यान दें कि धाराओं को इसका समर्थन करने के लिए विशिष्ट नहीं होना चाहिए; संग्रह कक्षाएं Spliterator के साथ स्ट्रीम बनाती हैं जो इसकी विशेषताओं को जानता है, इसलिए संग्रह के लिए एक विशेष कार्यान्वयन की आवश्यकता नहीं है, केवल साझा जानकारी को इस विशेष जानकारी का लाभ उठाने के लिए अद्यतन करना।

+1

आपने 'sorted()' भाग का जवाब नहीं दिया। मुझे पता चला कि यह 'शून्य' तुलनित्र के लिए सॉर्टिंग छोड़ देता है (जैसे प्रश्न के कोड का उपयोग करता है) लेकिन 'ट्रीसेट' और 'क्रमबद्ध (...)' कॉल संदर्भ के बावजूद, किसी भी गैर-नल 'तुलनित्र के लिए नहीं छोड़ता है उसी तुलनित्र उदाहरण के लिए ('शून्य' और 'तुलनाकर्ता' प्राकृतिक पहचान() 'समकक्ष पहचानने के बारे में बात न करें)।और यह वही है जब उदाहरण 'forEach' का उपयोग करता है जिसे स्पष्ट रूप से असाधारण माना जाता है, इसलिए वास्तविक तुलनाकर्ताओं के बावजूद सॉर्टिंग को छोड़ दिया जा सकता है ... – Holger

+4

@ होल्गर: ठीक है, हम जिन विशेषताओं को ट्रैक करते हैं उनमें से एक है "प्राकृतिक क्रम में क्रमबद्ध", जो एक पेड़ बिना किसी स्पष्ट तुलनित्र के रूप में जाना जाता है; दूसरे उदाहरण में, वर्तमान कार्यान्वयन ओ (एन) है। –

2

sorted() विधि आकार को नहीं बदलती है, इसलिए सिद्धांत रूप में यह संभव हो सकता है कि भविष्य में कार्यान्वयन stream().sorted().count()O(1) समय में एक श्रृंखला कर सकता है।

https://github.com/speedment/speedment पर स्ट्रीम इंटरफ़ेस के [गति] ओपन सोर्स कार्यान्वयन पर एक नज़र डालें। ये धाराएं अपनी पाइपलाइन का निरीक्षण कर सकती हैं और स्ट्रीम में एक या कई चरणों को अनुकूलित कर सकती हैं।

संबंधित मुद्दे