Using Google Guava (Google Commons), is there a way to merge two equally sized lists into one list, with the new list containing composite objects of the two input lists?
You can refer to underscore-java library.
Underscore-java
is a port of Underscore.js
for Java, and the zip
method can achieve the goal.
Following is a sample code & output :
$.zip(Arrays.asList("moe", "larry", "curly"), Arrays.asList("30", "40", "50"));
=> [[moe, 30], [larry, 40], [curly, 50]]
Looks like this is not currently in Guava, but is a desired feature. See this github issue, in particular Iterators.zip()
.
Here's a version with no explicit iteration, but it's getting pretty ugly.
List<Person> persons = ImmutableList.copyOf(Iterables.transform(
ContiguousSet.create(Range.closedOpen(0, names.size()),
DiscreteDomain.integers()),
new Function<Integer, Person>() {
@Override
public Person(Integer index) {
return new Person(names.get(index), ages.get(index));
}
}));
It's really not much better than having explicit iteration, and you probably want some level of bounds checking to ensure that the two inputs are indeed of the same size.
Just pretend this is a Guava method:
for (int i = 0; i < names.size(); i++) {
persons.add(new Person(names.get(i), ages.get(i)));
}
Here's a generic way to zip lists with vanilla Java. Lacking tuples, I opted to use a list of map entries (If you don't like to use map entries, introduce an additional class ZipEntry
or something).
public static <T1,T2> List<Map.Entry<T1,T2>> zip(List<T1> zipLeft, List<T2> zipRight) {
List<Map.Entry<T1,T2>> zipped = new ArrayList<>();
for (int i = 0; i < zipLeft.size(); i++) {
zipped.add(new AbstractMap.SimpleEntry<>(zipLeft.get(i), zipRight.get(i)));
}
return zipped;
}
To support arrays as well:
@SuppressWarnings("unchecked")
public static <T1,T2> Map.Entry<T1,T2>[] zip(T1[] zipLeft, T2[] zipRight) {
return zip(asList(zipLeft), asList(zipRight)).toArray(new Map.Entry[] {});
}
To make it more robust add precondition checks on list sizes etc, or introduce left join / right join semantics similar to SQL queries.
As of Guava 21, this is possible via Streams.zip():
List<Person> persons = Streams.zip(names.stream(), ages.stream(), Person::new)
.collect(Collectors.toList());