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

查看:29
本文介绍了相当于 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 的预期用例,因为它合并了元素之间的依赖关系.因此,该解决方案可能看起来不太优雅,因为您必须为谓词引入一个全状态变量:

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天全站免登陆