2014-09-18 12 views
6

मेरी स्प्रिंग आवेदन में में एक यादृच्छिक तत्व खोजने बनाम, मैं QuoteOfTheDay के एक दस्तावेज़ प्रकार के लिए एक काउचआधारित भंडार है। दस्तावेज़ बहुत ही बुनियादी है, बस प्रकार UUID, प्रकार स्ट्रिंग के मान क्षेत्र और के प्रकार के बनाए जाने का दिनांक दिनांक फ़ील्ड का एक आईडी क्षेत्र है।जावा 8 Stream.findAny() धारा

मेरी सेवा वर्ग में, मैं एक विधि है कि दिन के एक यादृच्छिक उद्धरण देता है। शुरू में मैं बस निम्नलिखित है, जो प्रकार Optional<QuoteOfTheDay> का एक तर्क लौटे कर की कोशिश की है, लेकिन यह प्रतीत होता है कि findAny() काफी हमेशा धारा में एक ही तत्व लौट आते हैं। इस समय केवल 10 तत्व हैं।

public Optional<QuoteOfTheDay> random() { 
    return StreamSupport.stream(repository.findAll().spliterator(), false).findAny(); 
} 

के बाद से मैं और अधिक यादृच्छिक कुछ करना चाहता था, मैं जिसके बाद सिर्फ एक QuoteOfTheDay रिटर्न लागू किया।

public QuoteOfTheDay random() { 
    int count = Long.valueOf(repository.count()).intValue(); 

    if(count > 0) { 
     Random r = new Random(); 

     List<QuoteOfTheDay> quotes = StreamSupport.stream(repository.findAll().spliterator(), false) 
       .collect(toList()); 

     return quotes.get(r.nextInt(count)); 
    } else { 
     throw new IllegalStateException("No quotes found."); 
    } 
} 

मैं सिर्फ उत्सुक कैसे स्ट्रीम के findAny() विधि वास्तव में काम करता है के बाद से यह यादृच्छिक होना प्रतीत नहीं होता हूँ।

धन्यवाद।

उत्तर

21

findAny() के पीछे कारण findFirst() पर अधिक लचीला विकल्प देना है। यदि आप एक विशिष्ट तत्व प्राप्त करने में रूचि नहीं रखते हैं, तो यह समानांतर धारा होने पर कार्यान्वयन प्रवाह को अधिक लचीलापन देता है।

लौटाए गए तत्व को यादृच्छिक बनाने के लिए कोई प्रयास नहीं किया जाएगा, यह findFirst() के समान गारंटी नहीं देता है, और इसलिए तेज़ हो सकता है।

यह वही है Javadoc विषय पर कहते हैं:

इस आपरेशन के व्यवहार को स्पष्ट रूप से गैर नियतात्मक है; यह स्ट्रीम में किसी भी तत्व का चयन करने के लिए स्वतंत्र है। यह समांतर संचालन में अधिकतम प्रदर्शन की अनुमति है; लागत यह है कि एक ही स्रोत पर कई आमंत्रण एक ही परिणाम वापस नहीं कर सकते हैं।

10

(एक स्थिर परिणाम वांछित है, तो findFirst (का उपयोग करें) के बजाय।) एक List में इकट्ठा न करें जब सभी आप चाहते हैं एक आइटम है। बस स्ट्रीम से एक आइटम चुनें। Stream संचालन के माध्यम से आइटम को चुनकर आप Integer.MAX_VALUE से बड़ी संख्या को भी संभाल सकते हैं और इस तथ्य को छिपाने के "दिलचस्प" तरीके की आवश्यकता नहीं है कि आप int (उस Long.valueOf(repository.count()).intValue() चीज़) तक लंबे समय तक कास्टिंग कर रहे हैं।

public Optional<QuoteOfTheDay> random() { 
    long count = repository.count(); 
    if(count==0) return Optional.empty(); 
    Random r = new Random(); 
    long randomIndex=count<=Integer.MAX_VALUE? r.nextInt((int)count): 
     r.longs(1, 0, count).findFirst().orElseThrow(AssertionError::new); 
    return StreamSupport.stream(repository.findAll().spliterator(), false) 
     .skip(randomIndex).findFirst(); 
} 
संबंधित मुद्दे