क्या मुझे एक संग्रह या एक स्ट्रीम वापस करनी चाहिए?


163

मान लीजिए कि मेरे पास एक विधि है जो एक सदस्य सूची में केवल-पढ़ने का दृश्य देता है:

class Team {
    private List < Player > players = new ArrayList < > ();

    // ...

    public List < Player > getPlayers() {
        return Collections.unmodifiableList(players);
    }
}

इसके अलावा मान लीजिए कि सभी क्लाइंट सूची में एक बार, तुरंत हो सकता है कि खिलाड़ियों को जेएलिस्ट या किसी चीज में डाल दिया जाए। ग्राहक बाद में निरीक्षण के लिए सूची में एक संदर्भ संग्रहीत नहीं करता है !

इस सामान्य परिदृश्य को देखते हुए, क्या मुझे इसके बजाय एक धारा लौटानी चाहिए?

public Stream < Player > getPlayers() {
    return players.stream();
}

या जावा में एक स्ट्रीम गैर-मुहावरेदार है? क्या वे हमेशा उसी अभिव्यक्ति के अंदर "समाप्त" होने के लिए डिज़ाइन किए गए थे जो वे बनाए गए थे?


12
यह निश्चित रूप से एक मुहावरे के रूप में गलत नहीं है। आखिरकार, players.stream()बस एक ऐसी विधि है जो कॉल करने वाले को एक धारा लौटाती है। असली सवाल यह है कि क्या आप वास्तव में कॉलर को सिंगल ट्रावेल करने के लिए बाध्य करना चाहते हैं, और उसे Collectionएपीआई पर आपके संग्रह तक पहुंच से भी वंचित करना चाहते हैं? हो सकता है कि कॉलर सिर्फ addAllएक और संग्रह के लिए करना चाहता है ?
मार्को टोपोलनिक

2
यह सब निर्भर करता है। आप हमेशा collection.stream () के साथ-साथ Stream.collect () भी कर सकते हैं। तो यह आप और उस फ़ंक्शन का उपयोग करने वाले कॉलर तक।
राजा अनबझगन

जवाबों:


222

जवाब है, हमेशा की तरह, "यह निर्भर करता है"। यह निर्भर करता है कि लौटा हुआ संग्रह कितना बड़ा होगा। यह इस बात पर निर्भर करता है कि परिणाम समय के साथ बदलता है या नहीं और परिणाम की महत्वपूर्ण संगति कैसे होती है। और यह इस बात पर बहुत निर्भर करता है कि उपयोगकर्ता उत्तर का उपयोग कैसे करता है।

सबसे पहले, ध्यान दें कि आप हमेशा स्ट्रीम से एक संग्रह प्राप्त कर सकते हैं, और इसके विपरीत:

// If API returns Collection, convert with stream()
getFoo().stream()...

// If API returns Stream, use collect()
Collection<T> c = getFooStream().collect(toList());

तो सवाल यह है, जो आपके कॉल करने वालों के लिए अधिक उपयोगी है।

यदि आपका परिणाम अनंत हो सकता है, तो केवल एक ही विकल्प है: स्ट्रीम।

यदि आपका परिणाम बहुत बड़ा हो सकता है, तो आप शायद स्ट्रीम पसंद करते हैं, क्योंकि हो सकता है कि इसे एक बार में भौतिक रूप देने में कोई मूल्य न हो, और ऐसा करने से महत्वपूर्ण ढेर दबाव पैदा हो सकता है।

यदि सभी कॉलर ऐसा करने जा रहा है, तो इसके माध्यम से खोज (खोज, फ़िल्टर, एग्रीगेट) करना चाहिए, तो आपको स्ट्रीम पसंद करनी चाहिए, क्योंकि स्ट्रीम में ये बिल्ट-इन पहले से हैं और संग्रह को भौतिक बनाने की कोई आवश्यकता नहीं है (खासकर यदि उपयोगकर्ता प्रक्रिया नहीं कर सकता है। संपूर्ण परिणाम।) यह एक बहुत ही सामान्य मामला है।

यहां तक ​​कि अगर आपको पता है कि उपयोगकर्ता इसे कई बार प्रसारित करेगा या इसे इधर-उधर रखेगा, तो भी आप इसके बजाय स्ट्रीम को वापस करना चाह सकते हैं, इस तथ्य के लिए कि आप जो भी संग्रह करना चाहते हैं उसे चुनें (जैसे, ArrayList) फार्म वे चाहते हैं, और फिर फोन करने वाले को इसे वैसे भी कॉपी करना होगा। यदि आप एक धारा वापस करते हैं, तो वे कर सकते हैं collect(toCollection(factory))और इसे ठीक उसी रूप में प्राप्त कर सकते हैं जैसा वे चाहते हैं।

उपरोक्त "पसंद स्ट्रीम" मामले ज्यादातर इस तथ्य से प्राप्त होते हैं कि स्ट्रीम अधिक लचीला है; आप इसे एक संग्रह में संग्रहित करने की लागत और बाधाओं के कारण बिना इसका उपयोग करने के लिए देर से बाँध सकते हैं।

एक मामला जहां आपको एक संग्रह लौटना चाहिए, जब मजबूत स्थिरता की आवश्यकताएं हैं, और आपको एक चलती लक्ष्य का एक सुसंगत स्नैपशॉट तैयार करना होगा। फिर, आप तत्वों को एक संग्रह में रखना चाहेंगे जो नहीं बदलेगा।

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


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

8
@ मार्को भले ही आप अपने प्रश्न को इतने संकीर्ण रूप से परिभाषित करते हों, फिर भी मैं आपके निष्कर्ष से असहमत हूं। शायद आप यह मान रहे हैं कि स्ट्रीम बनाना किसी अपरिवर्तनीय आवरण के साथ संग्रह को लपेटने से कहीं अधिक महंगा है? (और, यहां तक ​​कि अगर आप नहीं करते हैं, तो रैपर पर आपको मिलने वाला स्ट्रीम व्यू आप मूल से भी बदतर है, क्योंकि अनमॉडिफ़िबिलिस्ट स्प्लिटर को ओवरराइड नहीं करता है (), आप प्रभावी रूप से सभी समानता खो देंगे।) परिचित पूर्वाग्रह; आपने वर्षों से संग्रह जाना है, और यह आपको नए चेहरे का अविश्वास कर सकता है।
ब्रायन गोएटज़

5
@MarkoTopolnik ज़रूर। मेरा लक्ष्य सामान्य एपीआई डिजाइन प्रश्न को संबोधित करना था, जो एफएक्यू बन रहा है। लागत के बारे में, ध्यान दें कि, यदि आपके पास पहले से कोई भौतिक संग्रह नहीं है, तो आप वापस लौट सकते हैं या रैप कर सकते हैं (ओपी करता है, लेकिन अक्सर एक नहीं होता है), गेट्टर विधि में एक संग्रह को भौतिक बनाना एक धारा को लौटाने और देने से कोई सस्ता नहीं है फोन करने वाले को एक (और निश्चित रूप से शुरुआती भौतिककरण बहुत अधिक महंगा हो सकता है, यदि कॉलर को इसकी आवश्यकता नहीं है या यदि आप ArrayList को लौटाते हैं, लेकिन कॉलर ट्रीसेट चाहता है।) लेकिन स्ट्रीम नया है, और लोग अक्सर इसे अधिक $ $ $ मान लेते हैं। यह है।
ब्रायन गोएट्ज़

4
@MarkoTopolnik जबकि इन-मेमोरी एक बहुत ही महत्वपूर्ण उपयोग-मामला है, कुछ अन्य मामले भी हैं जिनका अच्छा समानांतर समर्थन है, जैसे कि गैर-ऑर्डर किए गए स्ट्रीम (जैसे, Stream.generate)। हालाँकि, जहाँ स्ट्रीम एक खराब फिट है, प्रतिक्रियाशील उपयोग का मामला है, जहाँ डेटा यादृच्छिक विलंबता के साथ आता है। उसके लिए, मैं RxJava का सुझाव दूंगा।
ब्रायन गोएट्ज़

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

63

मेरे पास ब्रायन गोएत्ज़ के उत्कृष्ट उत्तर में जोड़ने के लिए कुछ बिंदु हैं ।

"गेट्टर" स्टाइल विधि कॉल से स्ट्रीम को वापस करना काफी सामान्य है। जावा 8 javadoc में स्ट्रीम उपयोग पृष्ठ देखें और पैकेज के अलावा अन्य तरीकों के लिए "विधियों ... उस स्ट्रीम को खोजें" java.util.Stream। ये विधियां आमतौर पर उन वर्गों पर होती हैं जो किसी चीज के कई मूल्यों या एकत्रीकरण का प्रतिनिधित्व करते हैं या कर सकते हैं। ऐसे मामलों में, एपीआई आमतौर पर उनमें से संग्रह या सरणियाँ लौटाते हैं। ब्रायन ने अपने उत्तर में जिन सभी कारणों का उल्लेख किया है, उनके लिए यहां स्ट्रीम-रिटर्न विधियों को जोड़ना बहुत ही लचीला है। इनमें से कई वर्गों में पहले से ही संग्रह- या सरणी-वापसी के तरीके हैं, क्योंकि कक्षाएं स्ट्रीम एपीआई से पहले हैं। यदि आप एक नया एपीआई डिज़ाइन कर रहे हैं, और यह स्ट्रीम-रिटर्निंग विधियों को प्रदान करने के लिए समझ में आता है, तो संग्रह-वापसी के तरीकों को भी जोड़ना आवश्यक नहीं हो सकता है।

ब्रायन ने एक संग्रह में मूल्यों को "भौतिक" करने की लागत का उल्लेख किया। इस बिंदु को बढ़ाने के लिए, वास्तव में यहां दो लागतें हैं: संग्रह में भंडारण मूल्यों की लागत (मेमोरी आवंटन और नकल) और पहली जगह में मूल्यों को बनाने की लागत भी। बाद की लागत को अक्सर स्ट्रीम के आलसीपन वाले व्यवहार का लाभ उठाकर कम या कम किया जा सकता है। इसका एक अच्छा उदाहरण एपीआई हैं java.nio.file.Files:

static Stream<String>  lines(path)
static List<String>    readAllLines(path)

न केवल readAllLinesपरिणाम सूची में संग्रहीत करने के लिए, पूरे फ़ाइल सामग्री को मेमोरी में रखना पड़ता है, बल्कि सूची को वापस करने से पहले फ़ाइल को बहुत अंत तक पढ़ना पड़ता है। linesया बिल्कुल नहीं - विधि के लगभग तुरंत बाद यह कुछ सेटअप प्रदर्शन किया है बाद में जब यह आवश्यक है जब तक फ़ाइल पढ़ने और लाइन तोड़ने छोड़ने लौट सकते हैं,। यह एक बहुत बड़ा लाभ है, यदि उदाहरण के लिए, कॉलर को केवल पहले दस लाइनों में रुचि है:

try (Stream<String> lines = Files.lines(path)) {
    List<String> firstTen = lines.limit(10).collect(toList());
}

निश्चित रूप से काफी मेमोरी स्पेस को बचाया जा सकता है यदि कॉलर केवल एक पैटर्न से मेल खाते लाइनों को वापस करने के लिए स्ट्रीम को फ़िल्टर करता है, आदि।

एक मुहावरा जो उभरता हुआ प्रतीत होता है, वह है getउपसर्ग -वापसी के तरीकों का नाम, उन चीजों के नाम के बहुवचन के बाद जिनका वे प्रतिनिधित्व करते हैं या होते हैं, बिना उपसर्ग के। साथ ही, stream()एक स्ट्रीम-रिटर्निंग विधि के लिए एक उचित नाम है, जब लौटाए जाने वाले मानों का केवल एक संभावित सेट है, कभी-कभी ऐसे वर्ग होते हैं जिनमें कई प्रकार के मान होते हैं। उदाहरण के लिए, मान लीजिए कि आपके पास कुछ ऐसी वस्तु है जिसमें विशेषताएँ और तत्व दोनों हैं। आप दो स्ट्रीम-रिटर्निंग API प्रदान कर सकते हैं:

Stream<Attribute>  attributes();
Stream<Element>    elements();

3
शानदार अंक। क्या आप इस बारे में अधिक कह सकते हैं कि आप उस नामकरण मुहावरे को कहाँ देख रहे हैं, और यह कितना कर्षण (भाप?) उठा रहा है। मुझे एक नामकरण सम्मेलन का विचार पसंद है, जिससे यह स्पष्ट हो जाता है कि आपको एक संग्रह बनाम एक संग्रह मिल रहा है - हालाँकि मैं अक्सर "get" पर IDE पूरा होने की उम्मीद करता हूं कि मुझे क्या मिल सकता है।
जोशुआ गोल्डबर्ग

1
मुझे उस नामकरण मुहावरे के बारे में भी बहुत दिलचस्पी है
चुनाव करें

5
@JoshuaGoldberg JDK ने इस नामकरण मुहावरे को अपनाया है, हालाँकि विशेष रूप से नहीं। विचार करें: CharSequence.chars () और .codePoints (), BufferedReader.lines (), और Files.lines (जावा 8 में मौजूद)। जावा 9 में, निम्नलिखित जोड़े गए हैं: Process.children (), NetworkInterface.addresses () ), Scanner.tokens (), Matcher.results (), java.xml.catalog.Catalog.catalogs ()। अन्य स्ट्रीम-रिटर्निंग विधियों को जोड़ा गया है जो इस मुहावरे का उपयोग नहीं करते हैं - Scanner.findAll () का ध्यान आता है - लेकिन बहुवचन संज्ञा मुहावरा JDK में उचित उपयोग में आया है।
स्टुअर्ट मार्क्स

1

क्या वे हमेशा उसी अभिव्यक्ति के अंदर "समाप्त" होने के लिए डिज़ाइन किए गए थे जो वे बनाए गए थे?

इस प्रकार उनका उपयोग अधिकांश उदाहरणों में किया जाता है।

नोट: एक स्ट्रीम लौटना एक आयेटर को अलग करने के लिए अलग नहीं है (बहुत अधिक अभिव्यंजक शक्ति के साथ भर्ती)

IMHO सबसे अच्छा समाधान है कि आप यह क्यों कर रहे हैं, और संग्रह को वापस नहीं करना है।

जैसे

public int playerCount();
public Player player(int n);

या यदि आप उन्हें गिनने का इरादा रखते हैं

public int countPlayersWho(Predicate<? super Player> test);

2
इस जवाब के साथ समस्या यह है कि लेखक को प्रत्येक क्रिया का अनुमान लगाने की आवश्यकता होगी जो ग्राहक करना चाहता है यह वर्ग पर तरीकों की संख्या में बहुत वृद्धि करेगा।
dkatzel

@dkatzel यह इस बात पर निर्भर करता है कि अंत उपयोगकर्ता लेखक हैं या वे किसी के साथ काम करते हैं। यदि अंतिम उपयोगकर्ता अनजाने हैं, तो आपको अधिक सामान्य समाधान की आवश्यकता है। आप अभी भी अंतर्निहित संग्रह तक पहुँच को सीमित करना चाह सकते हैं।
पीटर लॉरी

1

यदि स्ट्रीम परिमित है, और लौटी हुई वस्तुओं पर अपेक्षित / सामान्य संचालन है जो एक चेक अपवाद को फेंक देगा, तो मैं हमेशा एक संग्रह लौटाता हूं। क्योंकि यदि आप प्रत्येक वस्तु पर कुछ ऐसा करने जा रहे हैं जो एक चेक अपवाद को फेंक सकता है, तो आप स्ट्रीम से नफरत करेंगे। धाराओं के साथ एक वास्तविक कमी मैं वहाँ की जाँच के अपवादों से निपटने में असमर्थता है।

अब, शायद यह एक संकेत है कि आपको चेक किए गए अपवादों की आवश्यकता नहीं है, जो उचित है, लेकिन कभी-कभी वे अपरिहार्य हैं।


1

संग्रह के विपरीत, धाराओं में अतिरिक्त विशेषताएं हैं । किसी भी विधि द्वारा दी गई एक धारा हो सकती है:

  • परिमित या अनंत
  • समानांतर या अनुक्रमिक (डिफ़ॉल्ट रूप से साझा किए गए थ्रेडपूल के साथ जो किसी अनुप्रयोग के किसी अन्य भाग को प्रभावित कर सकता है)
  • आदेश दिया या गैर-आदेश दिया

ये अंतर संग्रह में भी मौजूद हैं, लेकिन वे स्पष्ट अनुबंध का हिस्सा हैं:

  • सभी संग्रहों का आकार है, Iterator / Iterable अनंत हो सकता है।
  • संग्रह स्पष्ट रूप से आदेशित या गैर-आदेशित हैं
  • समानांतर रूप से थ्रेड-सेफ्टी से परे कलेक्शन केयर कुछ नहीं है।

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

  • (परिमित, आदेशित, अनुक्रमिक)
  • (परिमित, आदेशित, समानांतर)
  • (परिमित, गैर-आदेशित, अनुक्रमिक) ...

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

स्ट्रीम को केवल एक विधि हस्ताक्षर में एक वैध विकल्प के रूप में छोड़ देता है जब कोई भी समस्या ऊपर नहीं होती है, जो शायद ही कभी होती है।

यह एक स्पष्ट अनुबंध के साथ विधि हस्ताक्षरों में अन्य डेटाटाइप्स का उपयोग करने के लिए बहुत सुरक्षित है (और अंतर्निहित थ्रेड-पूल प्रसंस्करण के बिना), जो गलती से डेटा को क्रमबद्धता, आकार या समानता (और थ्रेड्स के उपयोग) के बारे में गलत धारणाओं के साथ संसाधित करना असंभव बनाता है।


2
अनंत धाराओं के बारे में आपकी चिंताएँ निराधार हैं; सवाल यह है कि "क्या मुझे एक संग्रह या एक धारा वापस करनी चाहिए"। यदि संग्रह एक संभावना है, तो परिणाम परिभाषा परिमित है। इसलिए चिंता है कि कॉलर्स को एक अनंत पुनरावृत्ति का खतरा होगा, यह देखते हुए कि आप एक संग्रह लौटा सकते हैं , निराधार हैं। इस जवाब में बाकी सलाह केवल खराब है। यह मुझे लगता है जैसे आप किसी ऐसे व्यक्ति में भाग गए, जिसने स्ट्रीम का उपयोग किया था, और आप दूसरी दिशा में ओवर-रोटेट कर रहे हैं। समझ में आता है, लेकिन बुरी सलाह।
ब्रायन गोएत्ज

0

मुझे लगता है कि यह आपके परिदृश्य पर निर्भर करता है। हो सकता है, यदि आप अपना Teamकार्यान्वयन करते हैं Iterable<Player>, तो यह पर्याप्त है।

for (Player player : team) {
    System.out.println(player);
}

या एक कार्यात्मक शैली में:

team.forEach(System.out::println);

लेकिन अगर आप अधिक संपूर्ण और धाराप्रवाह एपीआई चाहते हैं, तो एक स्ट्रीम एक अच्छा समाधान हो सकता है।


ध्यान दें कि, ओपी पोस्ट किए गए कोड में, खिलाड़ी की गिनती लगभग एक अनुमान के अनुसार बेकार है ('1034 खिलाड़ी अब खेल रहे हैं, शुरू करने के लिए यहां क्लिक करें!') ऐसा इसलिए है क्योंकि आप एक परस्पर संग्रह का अपरिवर्तनीय दृश्य लौटा रहे हैं। , इसलिए अब आपको मिलने वाली गिनती अब से तीन माइक्रोसेकंड के बराबर नहीं हो सकती है। इसलिए एक संग्रह लौटाते समय आपको गणना करने के लिए एक "आसान" तरीका मिलता है (और वास्तव में, stream.count()बहुत आसान भी है), यह संख्या डिबगिंग या आकलन के अलावा किसी भी चीज़ के लिए वास्तव में बहुत सार्थक नहीं है।
ब्रायन गोएटज़

0

हालांकि कुछ अधिक हाई-प्रोफाइल उत्तरदाताओं ने सामान्य सलाह दी, मुझे आश्चर्य है कि किसी ने भी यह नहीं कहा:

यदि आपके पास पहले से ही एक "भौतिककृत" Collectionहाथ है (अर्थात यह कॉल से पहले ही बनाया गया था - जैसा कि दिए गए उदाहरण में है, जहां यह एक सदस्य फ़ील्ड है), तो इसे a में परिवर्तित करने का कोई मतलब नहीं है Stream। कॉल करने वाला आसानी से खुद ऐसा कर सकता है। जबकि, यदि कॉलर अपने मूल रूप में डेटा का उपभोग करना चाहता है, तो आप इसे Streamमूल संरचना की प्रतिलिपि को फिर से भौतिक बनाने के लिए निरर्थक कार्य करने के लिए बलों में परिवर्तित करते हैं।


-1

शायद एक स्ट्रीम फैक्टरी एक बेहतर विकल्प होगा। केवल स्ट्रीम के माध्यम से संग्रह को उजागर करने की बड़ी जीत यह है कि यह आपके डोमेन मॉडल की डेटा संरचना को बेहतर ढंग से एन्क्रिप्ट करता है। अपनी सूची या सेट के आंतरिक कामकाज को प्रभावित करने के लिए अपने डोमेन वर्गों के किसी भी उपयोग के लिए बस एक स्ट्रीम को उजागर करना असंभव है।

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


7
क्या यह पूरी तरह उद्धृत है? क्या कोई स्रोत है?
ज़ेरुस

-5

मेरे पास शायद 2 तरीके होंगे, एक को वापस करने के लिए Collectionऔर एक को संग्रह के रूप में वापस करने के लिए Stream

class Team
{
    private List<Player> players = new ArrayList<>();

// ...

    public List<Player> getPlayers()
    {
        return Collections.unmodifiableList(players);
    }

    public Stream<Player> getPlayerStream()
    {
        return players.stream();
    }

}

यह दोनों दुनिया के लिए सबसे अच्छा है। ग्राहक चुन सकते हैं कि वे सूची या स्ट्रीम चाहते हैं और उन्हें केवल स्ट्रीम प्राप्त करने के लिए सूची की एक अपरिवर्तनीय प्रतिलिपि बनाने के लिए अतिरिक्त ऑब्जेक्ट निर्माण नहीं करना है।

यह आपके API में केवल 1 और विधि जोड़ता है, इसलिए आपके पास बहुत अधिक विधियाँ नहीं हैं


1
क्योंकि वह इन दो विकल्पों के बीच चयन करना चाहता था और प्रत्येक के पेशेवरों और विपक्षों से पूछा। इसके अलावा यह सभी को इन अवधारणाओं की बेहतर समझ प्रदान करता है।
लिबर्ट पियू पिउ

कृपया ऐसा मत करो। एपीआई की कल्पना करो!
फ्रांस्वा गूटियर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.