Last active
May 10, 2020 05:53
-
-
Save smac89/5bdafdc2a10cf942afe003061bdaaba2 to your computer and use it in GitHub Desktop.
Java sliding windows via Streams
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.List; | |
import java.util.stream.IntStream; | |
import java.util.stream.Stream; | |
public class Main { | |
public static void main(String args[]) { | |
Stream<List<Integer>> stream = SlidingWindow.pagedStream(StreamableSupplier.fromStream(IntStream.range(1, 10000).boxed()), 5) | |
.apply(i -> i <= 100); | |
stream.forEach(System.out::println); | |
} | |
} |
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.ArrayList; | |
import java.util.Iterator; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.NoSuchElementException; | |
import java.util.Spliterators; | |
import java.util.function.Function; | |
import java.util.function.Predicate; | |
import java.util.stream.Stream; | |
import java.util.stream.StreamSupport; | |
public class SlidingWindow { | |
public static <T> Function<Predicate<? super T>, Stream<List<T>>> pagedStream(StreamableSupplier<T> supplier, final int pageSize) { | |
return pagedStream(supplier, pageSize, 1); | |
} | |
public static <T> Function<Predicate<? super T>, Stream<List<T>>> pagedStream(StreamableSupplier<T> supplier, | |
final int pageSize, | |
int slideAmount) { | |
return pagedStream(supplier, pageSize, slideAmount, 0); | |
} | |
public static <T> Function<Predicate<? super T>, Stream<List<T>>> pagedStream(StreamableSupplier<T> supplier, | |
final int pageSize, | |
final int slideAmount, | |
int offset) { | |
return (stopPredicate) -> StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<List<T>>() { | |
LinkedList<T> window = new LinkedList<>(); | |
boolean hasFinished = false; | |
{ | |
assert pageSize > 0; | |
assert slideAmount > 0; | |
for (int i = 0; i < offset; i++) { | |
T temp = supplier.get(); | |
if (!stopPredicate.test(temp)) { | |
hasFinished = true; | |
break; | |
} | |
} | |
} | |
@Override | |
public boolean hasNext() { | |
return !hasFinished; | |
} | |
@Override | |
public List<T> next() { | |
if (hasFinished) { | |
throw new NoSuchElementException("The iterator is empty!"); | |
} | |
hasFinished = populate(); | |
List<T> currWindow = new ArrayList<>(window); | |
if (!hasFinished) { | |
hasFinished = slide(); | |
} | |
return currWindow; | |
} | |
private boolean populate() { | |
boolean added = false; | |
while (window.size() < pageSize) { | |
T item = supplier.get(); | |
if (!stopPredicate.test(item)) { | |
break; | |
} | |
window.add(item); | |
added = true; | |
} | |
if (added) { | |
return window.size() != pageSize; | |
} | |
window.clear(); | |
return false; | |
} | |
private boolean slide() { | |
for (int p = 0; p < slideAmount; p++) { | |
if (!window.isEmpty()) { | |
window.pop(); | |
} else if (!stopPredicate.test(supplier.get())) { | |
return true; | |
} | |
} | |
return false; | |
} | |
}, 0), false); | |
} | |
} |
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.Iterator; | |
import java.util.Spliterators; | |
import java.util.function.Supplier; | |
import java.util.stream.Stream; | |
import java.util.stream.StreamSupport; | |
@FunctionalInterface | |
public interface StreamableSupplier<T> { | |
T get(); | |
static <T> StreamableSupplier<T> fromStream(Stream<T> stream) { | |
Iterator<T> streamIterator = stream.iterator(); | |
return streamIterator::next; | |
} | |
static <T> StreamableSupplier<T> fromSupplier(Supplier<T> supplier) { | |
return supplier::get; | |
} | |
default Stream<T> toStream() { | |
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<T>() { | |
@Override | |
public boolean hasNext() { | |
return true; | |
} | |
@Override | |
public T next() { | |
return get(); | |
} | |
}, 0), false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment