Java 8 में findAny () और findFirst () के बीच अंतर


90

मैं थोड़ा के बीच उलझन में हूँ Stream#findAny()और Stream#findFirst()के Streamजावा 8 में एपीआई।

मुझे जो समझ में आया वह यह है कि दोनों पहले मिलान तत्व को धारा से लौटाएंगे, उदाहरण के लिए, जब फिल्टर के साथ संयोजन में उपयोग किया जाता है?

तो, एक ही कार्य के लिए दो विधियाँ क्यों? क्या मैं कुछ भूल रहा हूँ?

जवाबों:


92

मुझे जो समझ में आया वह यह है कि दोनों पहली बार मिलान किए गए तत्व को स्ट्रीम से वापस करेंगे, उदाहरण के लिए, जब फिल्टर के साथ संयोजन में उपयोग किया जाता है?

यह सच नहीं है। जावदोक के अनुसार Stream#findAny():

एक रिटर्न Optional<T>का वर्णन कुछ धारा के तत्व, या एक खाली Optional<T>है, तो धारा खाली है। इस ऑपरेशन का व्यवहार स्पष्ट रूप से nondeterministic है; यह स्ट्रीम में किसी भी तत्व का चयन करने के लिए स्वतंत्र है। यह समानांतर संचालन में अधिकतम प्रदर्शन के लिए अनुमति देना है;

जबकि धारा का पहला तत्व कड़ाई से वर्णन Stream.findFirst()करेगा । वर्ग एक नहीं है तो मैं आप का मतलब है लगता है, विधि ।Optional<T>Stream.findOne().findFirst()


मुझे अभी भी समझ में नहीं आया है, इसलिए जो आप कह रहे हैं filterवह लागू होने के बाद भी है, findAnyक्या किसी भी तत्व को वापस कर सकता है, जिसमें शामिल फ़िल्टर से मेल नहीं खाता है?
कोरे तुगे

@KorayTugay - नहीं, फ़िल्टर के बाद, जो भी शेष तत्व मौजूद हैं, findAnyउसमें से किसी भी तत्व को वापस कर सकते हैं (जैसे) यादृच्छिक, विशेष रूप से समानांतर धारा के संचालन में
कृपापाकर

46

नहीं, दोनों स्ट्रीम के पहले तत्व को वापस नहीं करेंगे।

से Stream.findAny()(जोर मेरा):

एक रिटर्न Optionalका वर्णन कुछ तत्व धारा के, या एक खाली Optionalहै, तो धारा खाली है।

यह एक शॉर्ट-सर्कुलेटिंग टर्मिनल ऑपरेशन है।

इस ऑपरेशन का व्यवहार स्पष्ट रूप से nondeterministic है; यह स्ट्रीम में किसी भी तत्व का चयन करने के लिए स्वतंत्र है । यह समानांतर संचालन में अधिकतम प्रदर्शन के लिए अनुमति देना है; लागत यह है कि एक ही स्रोत पर कई इनवोकेशन समान परिणाम नहीं दे सकते हैं। (यदि एक स्थिर परिणाम वांछित है, तो findFirst()इसके बजाय उपयोग करें ।)

तो इसे और अधिक सरलता से रखने के लिए, यह स्ट्रीम के पहले तत्व को चुन सकता है या नहीं भी कर सकता है।

वर्तमान ओरेकल विशिष्ट कार्यान्वयन के साथ, मेरा मानना ​​है कि यह गैर-समानांतर पाइपलाइन में पहला तत्व लौटाएगा। हालांकि, एक समानांतर पाइपलाइन में, यह हमेशा नहीं होगा (उदाहरण के लिए निष्पादित करें System.out.println(IntStream.range(0, 100).parallel().findAny());, OptionalInt[50]जब मैंने इसे चलाया तो यह वापस आ गया)। किसी भी तरह, आपको उस पर भरोसा नहीं करना चाहिए ।


16

findFirst स्ट्रीम के पहले तत्वों को लौटाता है, लेकिन findAny स्ट्रीम में किसी भी तत्व का चयन करने के लिए स्वतंत्र है।

List<String> lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
List<String> lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

Optional<String> findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst();
Optional<String> fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny();

System.out.println(findFirst.get()); //Always print David
System.out.println(fidnAny.get()); //Print Jack/Jill/Julia :behavior of this operation is explicitly nondeterministic

1

समानांतर मोड में findAnyआदेश की गारंटी नहीं है, लेकिन findFirstकरता है।

मैंने अंतर दिखाने के लिए कुछ कोड स्निपेट लिखे, इसे देखें


1

स्ट्रीम फ़ाइंड फ़र्स्ट और फ़ाइंडएनी में पहले तत्व वापस आते हैं और बाकी को निष्पादित नहीं करते हैं, लेकिन समांतर स्ट्रैस में, यह कहने के लिए निष्क्रिय नहीं है कि ऑर्डर और समांतरस्ट्रीम बाकी संग्रह को निष्पादित करता है।

संदर्भ

समय 1:25:00


1

मैं सिर्फ इतना कहूंगा कि उपयोग करते समय findFirst()और से सावधान रहें findAny()

जैसा कि उनके जावदोक से ( यहां और यहां ) दोनों विधियां धारा से एक मनमाना तत्व लौटाती हैं - जब तक कि धारा का एक मुठभेड़ क्रम नहीं होता है , जिस स्थिति में कोई भी तत्व वापस findFirst()करते समय पहला तत्व findAny()वापस आ जाता है।

मान लें कि हमारे पास कस्टम listनाम आईएसबीएन और बुक नाम है। एक परिदृश्य के लिए इस उदाहरण को देखें:

public class Solution {
   private Integer ISBN;
   private String BookName;

public Solution(int i, String string) {
    ISBN =i;
    BookName = string;
}
//getters and setters
}

public static void main(String[] args) {
        List<Solution> Library = Arrays.asList(new Solution(12,"Java in Action"),new Solution(13,"Java 8"),new Solution(15,"Java 8 Features"),new Solution(16,"Java in Action"));
 System.out.println(Library.stream()
        .map(p->p.getBookName())
        .sorted(Comparator.reverseOrder())
        .findFirst());
    }

आउटपुट :Optional[Java in Action]

पुस्तक का नाम समान होने पर परिदृश्य हो सकते हैं लेकिन आईएसबीएन संख्या भिन्न होती है, उस मामले में छंटनी और पुस्तक को ढूंढना काफी हद तक समान हो सकता है findAny()और गलत परिणाम देगा। ऐसे परिदृश्य के बारे में सोचें जहां 5 पुस्तकों को "जावा संदर्भ" नाम दिया गया है, लेकिन आईएसबीएन की अलग-अलग संख्याएँ हैं और findFirst()नाम से पुस्तक उसी के परिणामस्वरूप होगी findAny()

एक परिदृश्य के बारे में सोचो जहां:

 ISBN    Name Of book
+-----+------------------+
| 100 | Java-8 in Action |
+-----+------------------+
| 101 | Java-8 in Action |
+-----+------------------+
| 102 | Java-8 in Action |
+-----+------------------+
| 103 | Java-8 in Action |
+-----+------------------+
| 104 | Java-8 in Action |
+-----+------------------+

यहाँ findFirst () और findAny () BookByName पर छाँटे जाने पर भी वही परिणाम देगा।

विस्तृत लेख:


-1

जब Streamअनियंत्रित होता है, findFirst()और findAny()समान होते हैं। लेकिन जब Streamआदेश दिया जाता है, findAny()तो बेहतर होगा।


यह गलत है। इन विधियों में से कोई भी "बेहतर" नहीं है, क्योंकि उनके व्यवहार और उपयोग के मामले पूरी तरह से अलग हैं। इसके अलावा, Stream"आदेश" होने से आपका क्या मतलब है ? यह हमेशा आदेश दिया जाता है ( Streamजब इसे समानांतर में नहीं किया जाता है तो हर बार उसी क्रम में ऑपरेशन निष्पादित किए जाते हैं ), लेकिन शायद उपयोगकर्ता द्वारा छांटा नहीं गया है।
जेजोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.