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.

Answer from DrGodCarl on Stack Overflow
Top answer
1 of 16
94

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.

2 of 16
53

I'd often use the following idiom. I admit it is debatable whether it is clearer.

Iterator<String> i1 = names.iterator();
Iterator<String> i2 = things.iterator();
while (i1.hasNext() && i2.hasNext()) {
    map.put(i1.next(), i2.next());
}
if (i1.hasNext() || i2.hasNext()) complainAboutSizes();

It has the advantage that it also works for Collections and similar things without random access or without efficient random access, like LinkedList, TreeSets or SQL ResultSets. For example, if you'd use the original algorithm on LinkedLists, you've got a slow Shlemiel the painter algorithm which actually needs n*n operations for lists of length n.

As 13ren pointed out, you can also use the fact that Iterator.next throws a NoSuchElementException if you try to read after the end of one list when the lengths are mismatched. So you'll get the terser but maybe a little confusing variant:

Iterator<String> i1 = names.iterator();
Iterator<String> i2 = things.iterator();
while (i1.hasNext() || i2.hasNext()) map.put(i1.next(), i2.next());
🌐
Baeldung
baeldung.com › home › java › java collections › java map › combining two lists into a map in java
Combining Two Lists Into a Map in Java | Baeldung
June 27, 2025 - We then iterate through each element in KEY_LIST using a for loop, and for each element, we retrieve the corresponding element from VALUE_LIST using the same index i. Then, the put() method fills the key-value pair into the result map. Stream API provides many concise and efficient ways to manipulate Java collections. So next, let’s use the Java Stream API to associate two lists:
Discussions

Creating Map composed of 2 Lists using stream().collect in Java - Stack Overflow
4 How to create a map from list with java-streams? More on stackoverflow.com
🌐 stackoverflow.com
November 11, 2016
collections - Java 8 Collect two Lists to Map by condition - Stack Overflow
I have an object: public class CurrencyItem { private CurrencyName name; private BigDecimal buy; private BigDecimal sale; private Date date; //... } where CurrencyName is one o... More on stackoverflow.com
🌐 stackoverflow.com
November 28, 2015
Best way in java to merge two lists to one map? - Stack Overflow
Possible Duplicate: Clearest way to combine two lists into a map (Java)? Given this: List integers = new ArrayList (); List strings = new Arr... More on stackoverflow.com
🌐 stackoverflow.com
September 1, 2010
java - Streaming two lists into a map - Stack Overflow
I'm trying to learn java 8 streams and i'm having trouble converting the following code into streams · Copyparents = new ArrayList() ... children = new ArrayList() ... Map> result = new HashMap>(); for (Integer parentId : parents) ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Electro4u
electro4u.net › blog › combining-two-lists-into-a-map-in-java---1294
Combining Two Lists into a Map in Java |
You can use the java.util.stream.Collectors.toMap method to do this. The following code shows an example of how this can be done: List<String> list1 = Arrays.asList("a", "b", "c"); List<Integer> list2 = Arrays.asList(1, 2, 3); Map<String, Integer> map = list1.stream().collect(Collectors.toMap( ...
🌐
GitHub
gist.github.com › HoweChen › 533185dfde92c677f19d6745ae54bbc7
[zip two lists to map]#Java · GitHub
[zip two lists to map]#Java. GitHub Gist: instantly share code, notes, and snippets.
Top answer
1 of 2
7

This should be optimal. You first build a map from the currencies to their commercial banks. Then you run through your centrals building a map from commercial to central (looked up in the first map).

    List<CurrencyItem> currenciesByCommercialBank = new ArrayList<>();
    List<CurrencyItem> currenciesByCentralBank = new ArrayList<>();
    // Build my lookup from CurrencyName to CommercialBank.
    Map<CurrencyName, CurrencyItem> commercials = currenciesByCommercialBank
            .stream()
            .collect(
                    Collectors.toMap(
                            // Map from currency name.
                            ci -> ci.getName(),
                            // To the commercial bank itself.
                            ci -> ci));
    Map<CurrencyItem, CurrencyItem> commercialToCentral = currenciesByCentralBank
            .stream()
            .collect(
                    Collectors.toMap(
                            // Map from the equivalent commercial
                            ci -> commercials.get(ci.getName()),
                            // To this central.
                            ci -> ci
                    ));
2 of 2
4

The following code is O(n2), but it should be OK for small collections (which your lists probably are):

return currenciesByCommercialBank
    .stream()
    .map(c ->
        new AbstractMap.SimpleImmutableEntry<>(
            c, currenciesByCentralBank.stream()
                                      .filter(c2 -> c.currencyName == c2.currencyName)
                                      .findFirst()
                                      .get()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  }

The above is appropriate if you want to assert that currenciesByCentralBank contains a match for each item in currenciesByCommercialBank. If the two lists can have mismatches, then the following would be appropriate:

currenciesByCommercialBank
    .stream()
    .flatMap(c ->
        currenciesByCentralBank.stream()
                               .filter(c2 -> c.currencyName == c2.currencyName)
                               .map(c2 -> new AbstractMap.SimpleImmutableEntry<>(c, c2)))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

In this case the map will contain all the matches and won't complain about missing entries.

🌐
Baeldung
baeldung.com › home › java › java collections › java map › how to convert list to map in java
How to Convert List to Map in Java | Baeldung
April 4, 2025 - Learn several ways to convert a List into a Map using Custom Suppliers. ... Learn how to convert a List to a String using different techniques. ... How to convert between a List and a Set using plain Java, Guava or Apache Commons Collections.
🌐
CodingTechRoom
codingtechroom.com › tutorial › java-java-combine-two-lists-into-map
Java: How to Combine Two Lists Into a Map - CodingTechRoom
One of the simplest methods to combine two lists into a map is by using a for loop to iterate through the lists and put the key-value pairs into a `Map`. ... import java.util.HashMap; import java.util.Map; // Inside main method Map<String, Integer> map = new HashMap<>(); for (int i = 0; i < ...
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 40980948 › streaming-two-lists-into-a-map
java - Streaming two lists into a map - Stack Overflow
I'm trying to learn java 8 streams ... ArrayList<Integer>() ... children = new ArrayList<Intger>() ... Map<Integer, List<Integer>> result = new HashMap<Integer, List<Integer>>(); for (Integer parentId : parents) { result.put(parentId, new ...
🌐
Stack Overflow
stackoverflow.com › questions › 50165008 › create-map-from-two-lists-with-key-and-value-as-same-object
java - Create map from two lists with key and value as same object - Stack Overflow
key is the Object from one list and value is the same Object from the other list. do you really need a map when a key exact the same as a value? ... @dehasi if you read my question even though the object is same (override equals) there are properties which have different values ... I can see why you want to do something like this, but it seems very hacky. I'm sure if you tell us what you're trying to achieve, we can provide you with a better design. Regardless, the following will work with Java 10: var list1 = List.of("One", "Two", "Three"); var list2 = List.of("Two", "Three", "Four"); var set = Set.copyOf(list2); var map = list1.stream() .filter(set::contains) .collect(Collectors.toMap(k -> k, v -> list2.get(list2.indexOf(v)))); System.out.println(map);
🌐
How to do in Java
howtodoinjava.com › home › collections framework › convert list to map in java: tomap(), duplicate keys and order
Convert List to Map in Java: toMap(), Duplicate Keys and Order
September 23, 2022 - We cover the loop version, toMap() with duplicate keys, ordering and null values, grouping, and the Apache Commons and Guava helpers. A List keeps elements in order and allows duplicates, whereas a Map stores key-value pairs with unique keys and allows duplicate values. Converting a list into a map therefore needs two ...
🌐
Stack Overflow
stackoverflow.com › questions › 39945365 › how-to-map-two-lists-of-objects-by-id-efficiently
java - How to map two lists of objects by id efficiently - Stack Overflow
October 9, 2016 - List 1 has a getId() function and List 2 has a getList1Id() function, that gives the id of the object its supposed to map to in List 1. How do I do this in the most efficient way possible? ... Use java.util.Map instead of List.
🌐
Stack Overflow
stackoverflow.com › questions › 28565909 › convert-two-lists-into-keys-and-values-of-new-map-respectively
java - Convert two lists into keys and values of new map, respectively - Stack Overflow
February 17, 2015 - Guava lists this as a specifically rejected method here. ... There is exactly one function in these libraries that imperfectly works, and it is in Guava's Maps.uniqueIndex. You would expect it in MapUtils in Apache commons. ... Any function that does this work would have to take a stance on those two conditions.