Created
October 28, 2021 17:23
-
-
Save VAlux/0c21170367e2ccf4d701c12d0bfdc51e to your computer and use it in GitHub Desktop.
Java Spliterator implementation for a sliding window stream handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayDeque; | |
import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.Objects; | |
import java.util.Queue; | |
import java.util.Spliterator; | |
import java.util.function.Consumer; | |
import java.util.stream.Stream; | |
import java.util.stream.StreamSupport; | |
public final class SlidingWindowSpliterator<T> implements Spliterator<Stream<T>> { | |
private final Queue<T> windowBuffer; | |
private final Iterator<T> sourceIterator; | |
private final int windowSize; | |
private final int size; | |
public SlidingWindowSpliterator(Collection<T> source, int windowSize) { | |
this.windowBuffer = new ArrayDeque<>(windowSize); | |
this.sourceIterator = Objects.requireNonNull(source).iterator(); | |
this.windowSize = windowSize; | |
this.size = calculateSize(source, windowSize); | |
} | |
@Override | |
@SuppressWarnings("unchecked") | |
public boolean tryAdvance(Consumer<? super Stream<T>> action) { | |
if (windowSize < 1) { | |
return false; | |
} | |
while (sourceIterator.hasNext()) { | |
windowBuffer.add(sourceIterator.next()); | |
if (windowBuffer.size() == windowSize) { | |
// arrays in java... | |
action.accept(Arrays.stream((T[]) windowBuffer.toArray(new Object[0]))); | |
windowBuffer.poll(); | |
return sourceIterator.hasNext(); | |
} | |
} | |
return false; | |
} | |
@Override | |
public Spliterator<Stream<T>> trySplit() { | |
return null; | |
} | |
@Override | |
public long estimateSize() { | |
return size; | |
} | |
@Override | |
public int characteristics() { | |
return ORDERED | SIZED | NONNULL; | |
} | |
private int calculateSize(final Collection<T> source, final int windowSize) { | |
if (source.size() < windowSize) { | |
return 0; | |
} | |
return source.size() - windowSize + 1; | |
} | |
public static <T> Stream<Stream<T>> stream(final Collection<T> source, final int windowSize) { | |
return StreamSupport.stream(new SlidingWindowSpliterator<>(source, windowSize), false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment