簡體   English   中英

有序流的狀態過濾器

[英]Stateful filter for ordered stream

我有一個問題,我想知道是否有使用Streams的解決方案。

想象一下,你有一個有序的物體流; 讓我們假設一個整數流。

 Stream<Integer> stream = Stream.of(2,20,18,17,4,11,13,6,3,19,4,10,13....)

現在我想過濾所有值,其中值與此值之前的前一個數字之差大於n

stream.filter(magicalVoodoo(5))
// 2, 20, 4, 11, 3, 19, 4, 10 ...

我有可能這樣做嗎?

是的,這是可能的,但您需要一個有狀態謂詞來跟蹤進行比較的先前值。 這意味着它只能用於順序流:對於並行流,您將遇到競爭條件。

幸運的是,大多數流默認為順序,但如果您需要在來自未知源的流上執行此操作,您可能需要使用isParallel()進行檢查並拋出異常,或使用sequential()將其轉換為順序流。

一個例子:

public class DistanceFilter implements IntPredicate {

    private final int distance;
    private int previousValue;

    public DistanceFilter(int distance) {
        this(distance, 0);
    }

    public DistanceFilter(int distance, int startValue) {
        this.distance = distance;
        this.previousValue = startValue;
    }

    @Override
    public boolean test(int value) {
        if (Math.abs(previousValue - value) > distance) {
            previousValue = value;
            return true;
        }
        return false;
    }

    // Just for simple demonstration
    public static void main(String[] args) {
        int[] ints = IntStream.of(2, 20, 18, 17, 4, 11, 13, 6, 3, 19, 4, 10, 13)
                .filter(new DistanceFilter(5))
                .toArray();

        System.out.println(Arrays.toString(ints));
    }
}

我在這里使用了IntStream ,因為它是一個更好的類型,但是Stream<Integer> (或其他對象類型)的概念類似。

流不是為此類任務而設計的。 我會使用不同的方法來實現這一點,它不使用流。 但是,如果你真的必須使用流,那么解決方案必須避免由於流和lambda的設計而導致的某些限制,因此看起來非常h​​acky:

int[] previous = new int[1];
previous[0] = firstElement;
... = stream.filter(n -> {
        boolean isAllowed = (abs(n - previous[0]) > 5);
        if (isAllowed)
            previous[0] = n;
        return isAllowed;})

請注意,變量previous是一個單元素數組。 這是一個hack,因為lambda不允許修改變量(它可以修改數組的元素,但不能修改數組本身)。

暫無
暫無

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

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