相当于Scala dropWhile [英] Equivalent of Scala dropWhile

查看:119
本文介绍了相当于Scala dropWhile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难找到一种方法来跳过流的开头的一些元素,具体取决于谓词。

I'm struggling to find a way to skip some elements at the beginning of a stream depending on a predicate.

这样的事情:

dropWhile( n -> n < 3, Stream.of( 0, 1, 2, 3, 0, 1, 2, 3, 4 ) )
.forEach( System.out::println );





3   
0
1
2
3
4

这相当于Scala dropWhile

That is the equivalent of Scala dropWhile.

推荐答案

这种操作不是 Stream 的预期用例,因为它包含了元素之间的依赖关系。因此,解决方案可能看起来不太优雅,因为您必须为谓词引入一个state-full变量:

This kind of operation is not an intended use case for Streams as it incorporates a dependency between the elements. Therefore the solution might not look elegant as you have to introduce a state-full variable for your predicate:

class MutableBoolean { boolean b; }
MutableBoolean inTail = new MutableBoolean();

IntStream.of(0, 1, 2, 3, 0, 1, 2, 3, 4)
         .filter(i -> inTail.b || i >= 3 && (inTail.b = true))
         .forEach(System.out::println);

请注意,与您的示例相比,条件必须颠倒。

Note that the condition had to be reversed compared to your example.

当然,你可以在方法中隐藏讨厌的细节:

Of course, you can hide the nasty details in a method:

public static void main(String... arg) {
    dropWhile(n -> n < 3, Stream.of(0, 1, 2, 3, 0, 1, 2, 3, 4))
      .forEach(System.out::println);
}
static <T> Stream<T> dropWhile(Predicate<T> p, Stream<T> s) {
    class MutableBoolean { boolean b; }
    MutableBoolean inTail = new MutableBoolean();
    return s.filter(i -> inTail.b || !p.test(i) && (inTail.b = true));
}






更复杂,但是更清洁,可能更有效的方法是使用金属,即 Spliterator 界面:

static <T> Stream<T> dropWhile(Predicate<T> p, Stream<T> s) {
    Spliterator<T> sp = s.spliterator();
    return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(
            sp.estimateSize(), sp.characteristics() & ~Spliterator.SIZED) {
        boolean dropped;
        public boolean tryAdvance(Consumer<? super T> action) {
            if(dropped) return sp.tryAdvance(action);
            do {} while(!dropped && sp.tryAdvance(t -> {
                if(!p.test(t)) {
                    dropped=true;
                    action.accept(t);
                }
            }));
            return dropped;
        }
        public void forEachRemaining(Consumer<? super T> action) {
            while(!dropped) if(!tryAdvance(action)) return;
            sp.forEachRemaining(action);
        }
    }, s.isParallel());
}

此方法的使用方法与第一个 dropWhile 方法,但它甚至可以用于并行流,但效率不如你想象的那么高。

this method can be used the same way as the first dropWhile method, but it will work even with parallel streams, though not as efficient as you might wish.

这篇关于相当于Scala dropWhile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆