簡體   English   中英

在參數中給定多個條件時過濾 stream

[英]Filtering a stream when given multiple conditions in parameters

我正在嘗試創建一個 function ,它采用多個謂詞條件並根據這些條件過濾 stream 。 我找不到任何東西,但我的 retList 似乎只包含輸入而不是輸入的過濾版本。

以下是我得到的指示:

//TODO Make a Stream of Integer and set it equal to input for each predicate p on conditions, set this stream variable equals to the result of applying filter(p) to the stream. 完成每個循環后,將生成的 stream 收集到一個列表中,就像我們在之前的問題中所做的那樣,返回結果列表

這是我目前擁有的:

public static List<Integer> matchAll(Stream<Integer> input,  Predicate<Integer>... conditions) { 
    Stream<Integer> stream = input;
    Stream.of(conditions).peek(p -> stream.filter(p));

    List<Integer> retList = stream.collect(Collectors.toList());

    return retList;
}

這就是它的測試方式:

public static void main(String[] args) {
    Stream<Integer> stream = Stream.of(5,7,9,11,13,14,21,28,35,42,49,56,63,70,71);
    Predicate<Integer> p0 = n -> n > 10;
    Predicate<Integer> p1 = n -> n % 2 != 0;
    Predicate<Integer> p2 = n -> isPrime(n);
    System.out.println(Matcher.matchAll(stream, p0, p1, p2));
    // should get [11, 13, 71] 
}

但我實際得到的是輸入 [5,7,9,11,13,14,21,28,35,42,49,56,63,70,71]。

嘗試

public static List<Integer> matchAll(List<Integer> input, Predicate<Integer>... conditions) {
    Stream<Integer> streams = input.stream();
    for (Predicate<Integer> predicate : conditions) {
        streams = streams.filter(predicate);
    }
    return streams.collect(Collectors.toList());
}

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(5, 7, 9, 11, 13, 14, 21, 28, 35, 42, 49, 56, 63, 70, 71);
    Predicate<Integer> p0 = n -> n > 10;
    Predicate<Integer> p1 = n -> n % 2 != 0;
    Predicate<Integer> p2 = n -> isPrime(n);
    System.out.println(matchAll(list, p0, p1, p2)); // [11, 13, 71]
}

我在這里看到: https://stackoverflow.com/a/51187234/10910098

您可以簡單地在matchAll方法中創建一個復合Predicate並使用它來過濾輸入 stream 為:

public static List<Integer> matchAll(Stream<Integer> input, Predicate<Integer>... conditions) {
    Predicate<Integer> compositePredicate =
        Arrays.stream(conditions).reduce(Predicate::and).orElse(p -> true); // or else filter in all
    return input.filter(compositePredicate).collect(Collectors.toList());
}

正如Holger 所建議的,您也可以使用:

return Arrays.stream(conditions)
             .reduce(Predicate::and)
             .map(input::filter) // Optional.map here
             .orElse(input)
             .collect(Collectors.toList()); // terminal operation

在您當前的實現中,您不會將過濾的“結果”存儲在任何地方。 filter方法不會修改原來的 stream,它是不可變的,而是返回一個新的 stream,它只包含來自原始 stream 的匹配值。

實現此目的的一種方法是遍歷您的條件,將以前的 stream 替換為包含應用過濾的新條件:

public static List<Integer> matchAll(Stream<Integer> input,  Predicate<Integer>... conditions) { 
    Stream<Integer> stream = input;
    for (Predicate<Integer> condition : conditions) {
       stream = stream.filter(condition);
    }
    return stream.collect(Collectors.toList());
}

在您的 matchAll function 中,您可以考慮將以下 2 行更改為 1 行。 檢查它是否適用於數據輸入 stream 的多個謂詞過濾器。

從改變

Stream.of(conditions).peek(p -> stream.filter(p));

List<Integer> retList = stream.collect(Collectors.toList());

改成

List<Integer> retList = stream.filter(t -> Arrays.stream(conditions).allMatch(f -> f.test(t))).collect(Collectors.toList());

我認為它應該給出預期的 output。 希望能幫助到你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM