जावा स्ट्रीम: कई रेंज के साथ फ़िल्टर


9

मैं एक संसाधन को फ़िल्टर करने और एक क्षेत्र के आधार पर कुछ तत्वों को बाहर करने की कोशिश कर रहा हूं। बाहर करने के लिए मेरे पास एक सेट है (जिसमें एक आईडी है जिसे बाहर रखा जाना चाहिए) और एक सूची (इसमें कई प्रकार के आईडी शामिल हैं जिन्हें बाहर करने की आवश्यकता है)। मैंने नीचे दिया गया तर्क लिखा है और मैं द्वितीय फ़िल्टर तर्क से संतुष्ट नहीं हूँ। क्या कोई बेहतर तरीका है जिसे हम जावा 8 के साथ कर सकते हैं? मुझे रेंज के साथ-साथ इसके लिए भी ऐसा करने की जरूरत है।

Set<String> extensionsToExclude = new HashSet<>(Arrays.asList("20","25","60","900"));
List<String> rangesToExclude = new ArrayList<>(Arrays.asList("1-10","20-25","50-70","1000-1000000"));
return directoryRecords.stream()
        .filter((directoryRecord) -> !extensionsToExclude.contains(directoryRecord.getExtensionNumber()))
        .filter((directoryRecord -> {
            Boolean include = true;
            for(String s : rangesToExclude) {
                String [] rangeArray = s.split("-");
                Integer extension = Integer.parseInt(directoryRecord.getExtensionNumber());
                if(extension <= Integer.parseInt(rangeArray[0]) && extension >= Integer.parseInt(rangeArray[1])) {
                    include = false;
                }
            }
            return include;
        }))
        .collect(Collectors.toList());

धन्यवाद :)


3
Booleanजब आपको सिर्फ एक booleanमूल्य की आवश्यकता हो तो वस्तुओं का उपयोग न करें । हालांकि यहां, चर includeपूरी तरह से अप्रचलित है। जब तभी संभव परिवर्तन से है trueकरने के लिए false, आप बदल सकते हैं include = false;के साथ return false;अंतिम परिणाम के रूप में पहले से ही निर्धारित किया गया है। फिर, return include;अंत में प्रतिस्थापित किया जा सकता है return true;और हटाया गया चर घोषणा। और चूंकि directoryRecordलूप में कभी नहीं बदलता है, आप लूप से Integer extension = Integer.parseInt(directoryRecord.getExtensionNumber());पहले स्थानांतरित कर सकते हैं (और बदल Integerसकते हैं int)।
होल्गर

जवाबों:


9

मैं इसे एक कस्टम Rangeवर्ग के साथ करूँगा , कुछ इस तरह:

class Range {
    private long start;
    private long end;

    Range(String start, String end) {
        this.start = Long.parseLong(start);
        this.end = Long.parseLong(end);
    }

    Range(String range) {
        this(range.split("-")[0], range.split("-")[1]);
    }

    boolean inRange(long n) {
        returns start <= n && n <= end;
    }
}

जो कुछ इस तरह संभव होगा:

List<Range> ranges = rangesToExclude.stream()
                     .map(Range::new).collect(Collectors.toList());
return directoryRecords.stream()
        .filter((directoryRecord) -> !extensionsToExclude
                                    .contains(directoryRecord.getExtensionNumber()))
        .filter(directoryRecord -> ranges.stream()
                                    .noneMatch(r -> r.isInRange(directoryRecord)))
        .collect(Collectors.toList());

मुझे व्यक्तिगत रूप से आपका पहला फ़िल्टर काफी अच्छा लगता है, जो संरक्षित है।


2
noneMatchजब हम बात कर रहे हों तो क्या यह नहीं होना चाहिए rangesToExclude? और मुझे लगता है, एक और भी सुंदर समाधान के साथ हो सकता है TreeSet<Range>...
Holger

यह वास्तव में होना चाहिए, मुझे नींद आ रही होगी।
ernest_k

@ernest_k समाधान के लिए धन्यवाद। मुझे यह वास्तव में सुरुचिपूर्ण लगता है।
यदवेंद्र राठौर

4

मैं ernest_k के उत्तर के समान सुझाव दूंगा Range

लेकिन इस दृष्टिकोण में आप बनाने के लिए दोनों संग्रह का उपयोग कर सकते हैं List<Range>(इसे "20"माना जा सकता है "20-20") और फ़िल्टर स्थिति को बदलने के साथ नकार का उपयोग करें anyMatch

List<Range> ranges = Stream.concat(extensionsToExclude.stream(), rangesToExclude.stream())
        .map(Range::creatRange).collect(Collectors.toList());

return directoryRecords.stream()
        .filter(directoryRecord -> !ranges.stream()
                .anyMatch(r -> r.isInRange(
                        Integer.parseInt(directoryRecord.getExtensionNumber()))
                ))
        .collect(Collectors.toList());
class Range {
    private int start;
    private int end;

    Range(String start, String end) {
        this.start = Integer.parseInt(start);
        this.end = Integer.parseInt(end);
    }

    static Range creatRange(String range) {
        if (range.contains("-")) {
            return new Range(range.split("-")[0], range.split("-")[1]);
        }
        return new Range(range, range);
    }

    boolean isInRange(int n) {
        return start <= n && n <= end;
    }
}

अपडेट करें

सृजन उस List<Range> rangesबिंदु से हटाने के लिए परिवर्तित किया जा सकता है जिससे Set<String> extensionsToExcludeनिर्मित सीमा में हैं List<String> rangesToExclud। फिर अनावश्यक श्रेणियां नहीं बनाई जाएंगी।

List<Range> ranges = rangesToExclude.stream().map(Range::creatRange)
        .collect(Collectors.toCollection(ArrayList::new));
extensionsToExclude.stream()
        .filter(v -> !ranges.stream()
                .anyMatch(r -> r.isInRange(Integer.parseInt(v))))
        .map(Range::creatRange)
        .forEach(ranges::add);

0

यदि श्रेणी की स्थिति सही है, तो आप जल्दी ब्रेक लगा सकते हैं, बजाय इसके कि सभी प्रविष्टियों का मूल्यांकन किया जाए।

if(extension >= Integer.parseInt(rangeArray[0]) && extension <= Integer.parseInt(rangeArray[1])) {
                    return true;
                }

अन्यथा केवल लूप के लिए गलत होने पर वापस लौटें।

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