Reputation: 2227
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
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
Reputation: 1
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
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
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