Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: vertical slicing an array of Lists

Tags:

java

java-8

I'm learning Java 8 lambdas and streams. So, I got an array of lists having varying lengths. Lists contain integers.

What would be the best way to collect vertical slices in another list of lists i.e collect all integers with index 0 from all original lists in slice 0, index 1 in slice 1 and so an until the length of the longest list (filling zeros for shorter lists)

I know it's trivial to hand code a couple of traditional loops for this but what about doing this using Java 8 features?

like image 885
tshymbra Avatar asked Jan 08 '15 09:01

tshymbra


2 Answers

That's a pretty interesting question - thanks for posting. I'm sure you'll see some interesting answers. Here's my attempt:

List<Integer> source[];
List<List<Integer>> slices = IntStream.range(0, Arrays.stream(source).mapToInt(List::size).max().getAsInt())
     .mapToObj(index -> Arrays.stream(source).map(list -> list.size() > index ? list.get(index) : 0)
         .collect(Collectors.toList()))
     .collect(Collectors.toList())
like image 128
sprinter Avatar answered Nov 16 '22 20:11

sprinter


Here is a solution which does not insert padding values for shorter Lists:

List<List<Integer>> slices = Stream.of(source).flatMap(l->
    IntStream.range(0, l.size()).mapToObj(i->new int[]{i, l.get(i)})
).collect(collectingAndThen(
    groupingBy(a->a[0], TreeMap::new, mapping(a->a[1], toList())),
    m->new ArrayList<>(m.values()))
);

this can be expanded to a zero-padding version like this:

int maxSize=IntStream.range(0,source.length).map(i->source[i].size()).max().orElse(0);
List<List<Integer>> slices = Stream.of(source).flatMap(l->
    Stream.concat(
      IntStream.range(0, l.size()).mapToObj(i->new int[]{i, l.get(i)}),
      IntStream.range(l.size(), maxSize).mapToObj(i->new int[]{i, 0})
    )
).collect(collectingAndThen(
    groupingBy(a->a[0], TreeMap::new, mapping(a->a[1], toList())),
    m->new ArrayList<>(m.values()))
);

Both solutions assume that you do import static java.util.stream.Collectors.*; as otherwise the code becomes really unreadable.

like image 2
Holger Avatar answered Nov 16 '22 22:11

Holger