For instance there are collections [1,2,3,4,5]
, [6,7,8]
, [9,0]
. Any way to avoid loops with iterators to interleave these collections via Java 8 stream API to get the following result - [1,6,9,2,7,0,3,8,4,5]
?
flatMap() V/s map() : It applies a function on each element of Stream and store return value into new Stream. It does not flatten the stream. But flatMap() is the combination of a map and a flat operation i.e, it applies a function to elements as well as flatten them.
Both of the functions map() and flatMap are used for transformation and mapping operations. map() function produces one output for one input value, whereas flatMap() function produces an arbitrary no of values as output (ie zero or more than zero) for each input value. Where R is the element type of the new stream.
The difference is that the map operation produces one output value for each input value, whereas the flatMap operation produces an arbitrary number (zero or more) values for each input value.
Does flatmap() method preserve the order of the streams? Yes, It does and map() also.
I am not sure if there's a simpler way with the Stream API, but you can do this using a stream over the indices of all the lists to consider:
static <T> List<T> interleave(List<List<T>> lists) {
int maxSize = lists.stream().mapToInt(List::size).max().orElse(0);
return IntStream.range(0, maxSize)
.boxed()
.flatMap(i -> lists.stream().filter(l -> i < l.size()).map(l -> l.get(i)))
.collect(Collectors.toList());
}
This gets the size of the greatest list in the given lists. For each index, it then flat maps it with a stream formed by the elements of each list at that index (if the element exist).
Then you can use it with
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1,2,3,4,5);
List<Integer> list2 = Arrays.asList(6,7,8);
List<Integer> list3 = Arrays.asList(9,0);
System.out.println(interleave(Arrays.asList(list1, list2, list3))); // [1, 6, 9, 2, 7, 0, 3, 8, 4, 5]
}
Using the protonpack library, you can use the method interleave
to do just that:
List<Stream<Integer>> lists = Arrays.asList(list1.stream(), list2.stream(), list3.stream());
List<Integer> result = StreamUtils.interleave(Selectors.roundRobin(), lists).collect(Collectors.toList());
System.out.println(result);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With