跳过Stream <T>中的最后x个元素

Sma*_*ker 8 java java-8 java-stream

如果我有Stream<T>,我可以轻松skip(long)地跳过流的前几个元素.但是,在流的末尾跳过给定数量的元素似乎没有等价物.

最明显的解决方案是使用limit(originalLength - elementsToRemoveAtEnd),但这需要事先知道初始长度,但情况并非总是如此.

有没有办法删除未知长度的流的最后几个元素而不必将其收集到a中Collection,计算元素并再次流式传输?

Hol*_*ger 9

对于Stream可能具有未知长度的s,没有通用的无存储解决方案.但是,您不需要收集整个流,只需要一个与要跳过的元素数一样大的存储:

static <T> Stream<T> skipLastElements(Stream<T> s, int count) {
    if(count<=0) {
      if(count==0) return s;
      throw new IllegalArgumentException(count+" < 0");
    }
    ArrayDeque<T> pending=new ArrayDeque<T>(count+1);
    Spliterator<T> src=s.spliterator();
    return StreamSupport.stream(new Spliterator<T>() {
        public boolean tryAdvance(Consumer<? super T> action) {
            while(pending.size()<=count && src.tryAdvance(pending::add));
            if(pending.size()>count) {
              action.accept(pending.remove());
              return true;
            }
          return false;
        }
        public Spliterator<T> trySplit() {
            return null;
        }
        public long estimateSize() {
            return src.estimateSize()-count;
        }
        public int characteristics() {
            return src.characteristics();
        }
    }, false);
}
public static void main(String[] args) {
    skipLastElements(Stream.of("foo", "bar", "baz", "hello", "world"), 2)
    .forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)