Will
Will

Reputation: 2227

How to zip multiple lists using java 8?

Given :

List<Integer> a = Arrays.asList(1,2,3);
List<Integer> b = Arrays.asList(1,2,3);
List<Integer> c = Arrays.asList(1,2,3);
List<Integer> d = Arrays.asList(1,2,3);

List<List<Integer>> sample = Arrays.asList(a,b,c,d);

How can I get this result with java 8?

[(1,1,1,1),(2,2,2,2),(3,3,3,3)]

Upvotes: 8

Views: 6120

Answers (4)

Klitos Kyriacou
Klitos Kyriacou

Reputation: 11642

/**
 * Zips lists. E.g. given [[1,2,3],[4,5,6]], returns [[1,4],[2,5],[3,6]].
 * @param listOfLists an N x M list
 * @returns an M x N list
 */
static <T> List<List<T>> zip(List<List<T>> listOfLists) {
    int size = listOfLists.get(0).size();
    List<List<T>> result = new ArrayList<>(size);
    for (int i = 0; i < size; ++i)
        result.add(
                listOfLists.stream()
                        .map(list -> list.get(i))
                        .collect(toList()));
    return result;
}

Upvotes: 4

If i right understand your question you need something like that:

private <T> List<List<T>> zip(Stream<Iterable<T>> stream) {
    return stream.collect(LinkedList::new,
            (lists, ts) -> {
                if (lists.isEmpty()) {
                    ts.forEach(t -> lists.add(new LinkedList<T>() {{
                        add(t);
                    }}));
                } else {
                    Iterator<List<T>> listIterator = lists.iterator();
                    Iterator<T> elementIterator = ts.iterator();
                    while (listIterator.hasNext() && elementIterator.hasNext()) {
                        listIterator.next().add(elementIterator.next());
                    }
                    while (listIterator.hasNext()) {
                        listIterator.next();
                        listIterator.remove();
                    }
                }
            }, (lists, lists2) -> {
                Iterator<List<T>> firstListIterator = lists.iterator();
                Iterator<List<T>> secondListIterator = lists2.iterator();
                while (firstListIterator.hasNext() && secondListIterator.hasNext()) {
                    firstListIterator.next().addAll(secondListIterator.next());
                }
                while (firstListIterator.hasNext()) {
                    firstListIterator.next();
                    firstListIterator.remove();
                }
            });
}

And you can get desired results with

System.out.println(zip(sample.stream()));

Upvotes: 0

Jure Kolenko
Jure Kolenko

Reputation: 809

Java streams don't natively support zipping.

If you want to do it manually, then using an IntStream as an 'iterator' over the lists is the way to go:

    List<Integer> l1 = Arrays.asList(1, 2, 3);
    List<Integer> l2 = Arrays.asList(2, 3, 4);

    List<Object[]> zipped = IntStream.range(0, 3).mapToObj(i -> new Object[]{l1.get(i), l2.get(i)}).collect(Collectors.toList());

    zipped.stream().forEach(i -> System.out.println(i[0] + " " + i[1]));

This is ugly, however, and not the 'java' way (as in using an array of 'properties' instead of a class).

Upvotes: 3

Youcef LAIDANI
Youcef LAIDANI

Reputation: 60026

If we consider that all the Lists have the same size, so why Java 8? you can just use a simple loop like this :

List<List<Integer>> list = new ArrayList<>();
for(int i = 0; i<a.size(); i++){
    list.add(Arrays.asList(a.get(i), b.get(i), c.get(i), d.get(i)));
}

Output

[[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]

I really insist to read this post here Is using Lambda expressions whenever possible in java good practice?

Upvotes: 0

Related Questions