为了账号安全,请及时绑定邮箱和手机立即绑定

有序流的状态过滤器

有序流的状态过滤器

长风秋雁 2021-11-11 17:00:53
我有一个问题,我想知道是否有使用 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 ...我有没有可能做到这一点?
查看完整描述

2 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

是的,这是可能的,但是您需要一个有状态的谓词来跟踪先前的值以进行比较。这确实意味着它只能用于顺序流:对于并行流,您会遇到竞争条件。


幸运的是,大多数流默认为顺序流,但如果您需要对来自未知来源的流执行此操作,您可能需要检查 usingisParallel()并抛出异常,或使用 将其转换为顺序流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>(或其他对象类型)相似。


查看完整回答
反对 回复 2021-11-11
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

流不是为这种任务而设计的。我会使用不同的方式来实现这一点,它不使用流。但是,如果您真的必须使用流,由于流和 lambda 的设计,该解决方案必须规避某些限制,因此看起来很hacky:


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 不允许修改变量(它可以修改数组的元素,但不能修改数组本身)。


查看完整回答
反对 回复 2021-11-11
  • 2 回答
  • 0 关注
  • 118 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信