Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to transform a Java stream into a sliding window?

What is the recommended way to transform a stream into a sliding window?

For instance, in Ruby you could use each_cons:

irb(main):020:0> [1,2,3,4].each_cons(2) { |x| puts x.inspect } [1, 2] [2, 3] [3, 4] => nil irb(main):021:0> [1,2,3,4].each_cons(3) { |x| puts x.inspect } [1, 2, 3] [2, 3, 4] => nil 

In Guava, I found only Iterators#partition, which is related but no sliding window:

final Iterator<List<Integer>> partition =    Iterators.partition(IntStream.range(1, 5).iterator(), 3); partition.forEachRemaining(System.out::println); --> [1, 2, 3] [4] 
like image 606
Philipp Claßen Avatar asked Dec 08 '15 14:12

Philipp Claßen


People also ask

Are Java 8 streams lazy?

The Java 8 Streams API is fully based on the 'process only on demand' strategy and hence supports laziness. In the Java 8 Streams API, the intermediate operations are lazy and their internal processing model is optimised to make it being capable of processing the large amount of data with high performance.

Can you break a stream in Java?

Because the loop is internal you cannot call break on it.

What does stream of () method in Java?

Stream of(T t) returns a sequential Stream containing a single element. Syntax : static Stream of(T t) Parameters: This method accepts a mandatory parameter t which is the single element in the Stream. Return Value: Stream of(T t) returns a sequential Stream containing the single specified element.


1 Answers

There's no such function in the API as it supports both sequential and parallel processing and it's really hard to provide an efficient parallel processing for sliding window function for arbitrary stream source (even efficient pairs parallel processing is quite hard, I implemented it, so I know).

However if your source is the List with fast random access, you can use subList() method to get the desired behavior like this:

public static <T> Stream<List<T>> sliding(List<T> list, int size) {     if(size > list.size())          return Stream.empty();     return IntStream.range(0, list.size()-size+1)                     .mapToObj(start -> list.subList(start, start+size)); } 

Similar method is actually available in my StreamEx library: see StreamEx.ofSubLists().

There are also some other third-party solutions which don't care about parallel processing and provide sliding functionality using some internal buffer. For example, protonpack StreamUtils.windowed.

like image 174
Tagir Valeev Avatar answered Oct 02 '22 21:10

Tagir Valeev