प्रवाह में उदाहरण देखें


80

मेरी निम्नलिखित अभिव्यक्ति है:

scheduleIntervalContainers.stream()
        .filter(sic -> ((ScheduleIntervalContainer) sic).getStartTime() != ((ScheduleIntervalContainer)sic).getEndTime())
        .collect(Collectors.toList());

... जहां scheduleIntervalContainersतत्व प्रकार है ScheduleContainer:

final List<ScheduleContainer> scheduleIntervalContainers

क्या फ़िल्टर से पहले प्रकार की जांच करना संभव है?

जवाबों:


132

आप filterकेवल ScheduleIntervalContainerउदाहरण रखने के लिए एक और आवेदन कर सकते हैं , और एक mapवसीयत जोड़ने से आप बाद की जातियों को बचा पाएंगे:

scheduleIntervalContainers.stream()
    .filter(sc -> sc instanceof ScheduleIntervalContainer)
    .map (sc -> (ScheduleIntervalContainer) sc)
    .filter(sic -> sic.getStartTime() != sic.getEndTime())
    .collect(Collectors.toList());

या, जैसा कि होल्गर ने टिप्पणी की थी, यदि आप उस शैली को पसंद करते हैं, तो आप लैम्बडा के भावों को विधि संदर्भों से बदल सकते हैं:

scheduleIntervalContainers.stream()
    .filter(ScheduleIntervalContainer.class::isInstance)
    .map (ScheduleIntervalContainer.class::cast)
    .filter(sic -> sic.getStartTime() != sic.getEndTime())
    .collect(Collectors.toList());

123
या .filter(ScheduleIntervalContainer.class::isInstance) .map(ScheduleIntervalContainer.class::cast), आप जो भी शैली पसंद करते हैं।
होल्गर

IDEA और Java8 में, यदि उपरोक्त स्निपेट को सूची <ScheduleContainer> ScheduleIntervalContainers को सौंपा गया है, तो यह अभी भी मुझे सूची के लिए परिणाम देने का संकेत देता है <ScheduleContainer> ScheduleIntervalContainers स्पष्ट रूप से, क्या आप जानते हैं कि क्यों?
। प्रतीक

@ K.Symbol क्या आपने a List<ScheduleContainer>या a को असाइन करने का प्रयास किया List<ScheduleIntervalContainer>? यह उत्तरार्द्ध होना चाहिए।
एरन

119

एक सुंदर सुरुचिपूर्ण विकल्प वर्ग के विधि संदर्भ का उपयोग करना है:

scheduleIntervalContainers
  .stream()
  .filter( ScheduleIntervalContainer.class::isInstance )
  .map( ScheduleIntervalContainer.class::cast )
  .filter( sic -> sic.getStartTime() != sic.getEndTime())
  .collect(Collectors.toList() );

इस शैली का क्या फ़ायदा है, जिसका उपयोग करने के लिए Instof और (ScheduleIntervalContainer) की तुलना में किया गया है?
मेग्विंड

@MageWind जो ज्यादातर स्टाइल की बात है। कुछ लोग इसे पसंद करते हैं, क्योंकि आपको एक अन्य चर नाम (लैम्बडा पैरामीटर के लिए), अन्य को पेश करने की आवश्यकता नहीं है, क्योंकि यह थोड़ा कम बाइट कोड उत्पन्न करता है (हालांकि वास्तव में प्रासंगिक होने के लिए पर्याप्त अंतर नहीं है)।
होल्गर

यह वास्ताव में अच्छा है! लेकिन .classआवश्यकता क्यों है ? का isInstanceहिस्सा नहीं है Object? है Classजावा में एक वर्ग?
पोस्ट सेल्फ

@PostSelf वास्तव में, यह ScheduleIntervalContainerवास्तव में एक उदाहरण नहीं है।
नमन

15

@ Eran solution - दोनों में वर्ग नाम टाइप करने में एक छोटी समस्या है filterऔर mapत्रुटि-प्रवण है - दोनों स्थानों में वर्ग का नाम बदलना भूल जाना आसान है। एक बेहतर समाधान कुछ इस तरह होगा:

private static <T, R> Function<T, Stream<R>> select(Class<R> clazz) {
    return e -> clazz.isInstance(e) ? Stream.of(clazz.cast(e)) : null;
}

scheduleIntervalContainers
  .stream()
  .flatMap(select(ScheduleIntervalContainer.class))
  .filter( sic -> sic.getStartTime() != sic.getEndTime())
  .collect(Collectors.toList());   

हालाँकि Streamहर मिलान तत्व के लिए बनाने में एक प्रदर्शन दंड हो सकता है । विशाल डेटा सेट पर इसका उपयोग करने के लिए सावधान रहें। मैंने इसका हल @ टैगिर वेल्व से सीखा है


इस दृष्टिकोण में आपको NullPointerException का ध्यान रखना चाहिए, क्योंकि जो कुछ भी नहीं है , उसके select(A.class)लिए वापस आ जाएगा । जोड़ने से मदद मिलेगी। BTW: @ एरण का दृष्टिकोण अशक्त है। nullA.filter(Objects::nonNull)
लार्स गेंडनर

क्षमा करें, मेरा बुरा ... जावाडॉक flatMapकहता है "यदि एक मैप की गई धारा अशक्त है, तो इसके बजाय एक खाली स्ट्रीम का उपयोग किया जाता है।" तो आपका समाधान सही था, यहां तक ​​कि नल-फिल्टर के बिना भी।
लार्स जेंडरर

3
फिर भी (IMO) वापस लौटने के लिए अजीब nullजब आप सिर्फ एक खाली स्ट्रीम लौटा सकते थे
Alowaniak
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.