How to zip two Java Lists
Here's Java-8 solution using the Pair
class (like in @ZhekaKozlov answer):
public static <A, B> List<Pair<A, B>> zipJava8(List<A> as, List<B> bs) {
return IntStream.range(0, Math.min(as.size(), bs.size()))
.mapToObj(i -> new Pair<>(as.get(i), bs.get(i)))
.collect(Collectors.toList());
}
In Java 9 onwards you can use Map.entry()
:
public static <A, B> List<Map.Entry<A, B>> zipJava8(List<A> as, List<B> bs) {
return IntStream.range(0, Math.min(as.size(), bs.size()))
.mapToObj(i -> Map.entry(as.get(i), bs.get(i)))
.collect(Collectors.toList());
}
As per related question, you can use Guava (>= 21.0) to do this:
List<String> subjectArr = Arrays.asList("aa", "bb", "cc");
List<Long> numArr = Arrays.asList(2L, 6L, 4L);
List<Pair> pairs = Streams.zip(subjectArr.stream(), numArr.stream(), Pair::new)
.collect(Collectors.toList());
Note that the guava method is annotated as @Beta
, though what that means in practice is up to interpretation, the method has not changed since version 21.0.
To get an Iterator<C>
from an Iterator<A>
, an Iterator<B>
, and a BiFunction<A, B, C>
:
public static <A, B, C> Iterator<C> map(Iterator<A> a, Iterator<B> b, BiFunction<A, B, C> f) {
return new Iterator<C>() {
public boolean hasNext() {
return a.hasNext() && b.hasNext(); // This uses the shorter of the two `Iterator`s.
}
public C next() {
return f.apply(a.next(), b.next());
}
};
}
Use an ArrayList of Map.Entry<String, Long>
, checking that both arraylists have equal size (as it seems to be your requirement), like that:
List<Map.Entry<String,Long>> subjectNumArr = new ArrayList<>(numArr.size());
if (subjectArr.size() == numArr.size()) {
for (int i = 0; i < subjectArr.size(); ++i) {
subjectNumArr.add(new AbstractMap.SimpleEntry<String, Long>(subjectArr.get(i), numArr.get(i));
}
}
That's all the code you need!
Then, to iterate over the results, use something like:
for (Map.Entry<String, Long> entry : subjectNumArr) {
String key = entry.getKey();
Long value = entry.getValue();
}
or, you can simply get the pair at position i (keeping insertion order), by:
Map.Entry<String, Long> entry = subjectNumArr.get(i);
This can also hold duplicate entries, unlike the Map solution that I initially suggested, without requiring to define your own (Pair) class.
The operation you want is called zipping.
You need to implement a method zip
:
public static <A, B> List<Pair<A, B>> zip(List<A> as, List<B> bs) {
Iterator<A> it1 = as.iterator();
Iterator<B> it2 = bs.iterator();
List<Map.Entry<A, B>> result = new ArrayList<>();
while (it1.hasNext() && it2.hasNext()) {
result.add(Map.entry(it1.next(), it2.next()));
}
return result;
}
And you use it like this:
zip(subjectArr, numArr);