Skip to content

Commit

Permalink
add Streams.skipLast operator (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmoten authored Aug 3, 2023
1 parent 90acee8 commit 09943f7
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
6 changes: 6 additions & 0 deletions kool/src/main/java/org/davidmoten/kool/Stream.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import org.davidmoten.kool.internal.operators.stream.RetryWhen;
import org.davidmoten.kool.internal.operators.stream.Reverse;
import org.davidmoten.kool.internal.operators.stream.Skip;
import org.davidmoten.kool.internal.operators.stream.SkipLast;
import org.davidmoten.kool.internal.operators.stream.SkipUntil;
import org.davidmoten.kool.internal.operators.stream.Sorted;
import org.davidmoten.kool.internal.operators.stream.Split;
Expand Down Expand Up @@ -844,6 +845,11 @@ default Stream<List<T>> buffer(int size, int step) {
default Stream<T> skip(int size) {
return new Skip<T>(size, this);
}

default Stream<T> skipLast(int size) {
Preconditions.checkArgument(size >=0, "size must be non-negative");
return new SkipLast<T>(size, this);
}

default Stream<T> skipUntil(Predicate<? super T> predicate) {
return new SkipUntil<T>(this, predicate, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.davidmoten.kool.internal.operators.stream;

import java.util.NoSuchElementException;

import org.davidmoten.kool.Stream;
import org.davidmoten.kool.StreamIterator;
import org.davidmoten.kool.internal.util.RingBuffer;

public final class SkipLast<T> implements Stream<T> {

private final Stream<T> stream;
private final int size;

public SkipLast(int size, Stream<T> stream) {
this.stream = stream;
this.size = size;
}

@Override
public StreamIterator<T> iterator() {
RingBuffer<T> buffer = new RingBuffer<T>(size + 1);
StreamIterator<T> it = stream.iterator();
return new StreamIterator<T>() {

@Override
public boolean hasNext() {
loadNext();
return buffer.size() == size + 1;
}

@Override
public T next() {
loadNext();
if (buffer.size() == size + 1) {
return buffer.poll();
} else {
throw new NoSuchElementException();
}
}

@Override
public void dispose() {
it.dispose();
}

private void loadNext() {
while (buffer.size() < size + 1 && it.hasNext()) {
buffer.add(it.next());
}
}
};
}
}
25 changes: 25 additions & 0 deletions kool/src/test/java/org/davidmoten/kool/StreamTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,31 @@ public void testSkip() {
public void testSkipMoreThanAvailable() {
Stream.of(1, 2, 3, 4).skip(5).test().assertNoValuesOnly();
}

@Test
public void testSkipLast() {
Stream.of(1, 2, 3, 4).skipLast(2).test().assertValuesOnly(1, 2);
}

@Test
public void testSkipLastZero() {
Stream.of(1, 2, 3, 4).skipLast(0).test().assertValuesOnly(1, 2, 3, 4);
}

@Test
public void testSkipLastMoreThanAvailable() {
Stream.of(1, 2, 3, 4).skipLast(5).test().assertNoValuesOnly();
}

@Test(expected = NoSuchElementException.class)
public void testSkipLastNoSuchElement() {
Stream.empty().skipLast(5).iterator().next();
}

@Test(expected = IllegalArgumentException.class)
public void testSkipLastNegative() {
Stream.of(1, 2, 3, 4).skipLast(-1);
}

@Test
public void testTakeDisposes() {
Expand Down

0 comments on commit 09943f7

Please sign in to comment.