Been a while since this question was asked but these days I'm partial to something like:
public static <K, V> Map<K, V> zipToMap(List<K> keys, List<V> values) {
return IntStream.range(0, keys.size()).boxed()
.collect(Collectors.toMap(keys::get, values::get));
}
For those unfamiliar with streams, what this does is gets an IntStream
from 0 to the length, then boxes it, making it a Stream<Integer>
so that it can be transformed into an object, then collects them using Collectors.toMap
which takes two suppliers, one of which generates the keys, the other the values.
This could stand some validation (like requiring keys.size()
be less than values.size()
) but it works great as a simple solution.
EDIT:
The above works great for anything with constant time lookup, but if you want something that will work on the same order (and still use this same sort of pattern) you could do something like:
public static <K, V> Map<K, V> zipToMap(List<K> keys, List<V> values) {
Iterator<K> keyIter = keys.iterator();
Iterator<V> valIter = values.iterator();
return IntStream.range(0, keys.size()).boxed()
.collect(Collectors.toMap(_i -> keyIter.next(), _i -> valIter.next()));
}
The output is the same (again, missing length checks, etc.) but the time complexity isn't dependent on the implementation of the get
method for whatever list is used.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…