相当于Scala dropWhile

我正在努力寻找一种方法来跳过流的开头的一些元素,具体取决于谓词。

像这样的东西:

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

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

 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); 

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

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

 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  Stream dropWhile(Predicate p, Stream s) { class MutableBoolean { boolean b; } MutableBoolean inTail = new MutableBoolean(); return s.filter(i -> inTail.b || !p.test(i) && (inTail.b = true)); } 

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

 static  Stream dropWhile(Predicate p, Stream s) { Spliterator sp = s.spliterator(); return StreamSupport.stream(new Spliterators.AbstractSpliterator( sp.estimateSize(), sp.characteristics() & ~Spliterator.SIZED) { boolean dropped; public boolean tryAdvance(Consumer 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 action) { while(!dropped) if(!tryAdvance(action)) return; sp.forEachRemaining(action); } }, s.isParallel()); } 

此方法可以与第一个dropWhile方法相同的方式使用,但即使使用并行流也可以使用,但不如您希望的那样高效。

不幸的是,使用Java 8的唯一方法是使用Holger提供的解决方案。

但是,操作dropWhile(predicate)已添加到Java 9中,因此从JDK 9开始,您可以简单地:

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