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 - Map<String, Integer> result = new ... iv.next()); } assertEquals(EXPECTED_MAP, result); In this example, we create two Iterator objects, one for each list....
Discussions

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
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 - Merge Map<String, List<String> Java 8 Stream - Stack Overflow
I would like to merge two Map with JAVA 8 Stream: Map mapAdded ... More on stackoverflow.com
🌐 stackoverflow.com
java - Group by two lists in one map using lambda - Code Review Stack Exchange
I've got two collections: collection of rules, and collection of keys that can handle specific rules. Key have method boolean canHandle(Rule) to check whether specific key can handle specific rule ... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
🌐
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 < ...
🌐
CodingTechRoom
codingtechroom.com › question › combine-lists-into-map-java
How to Efficiently Combine Two Lists into a Map in Java - CodingTechRoom
import java.util.*; public class ListsToMap { static public void main(String[] args) { List<String> names = Arrays.asList("apple,orange,pear".split(",")); List<String> things = Arrays.asList("123,456,789".split(",")); Map<String,String> map = new LinkedHashMap<String,String>(); // ordered for (int i=0; i<names.size(); i++) { map.put(names.get(i), things.get(i)); // is there a clearer way? } System.out.println(map); } } Combining two lists into a map in Java can be done efficiently using various approaches.
🌐
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( ...
Top answer
1 of 6
23

You can do this by iterating over all the entries in mapAdded and merging them into mapGlobal.

The following iterates over the entries of mapAdded by calling forEach(action) where the action consumes the key and value of each entry. For each entry, we call merge(key, value, remappingFunction) on mapGlobal: this will either create the entry under the key k and value v if the key didn't exist or it will invoke the given remapping function if they already existed. This function takes the 2 lists to merge, which in this case, are first added to a TreeSet to ensure both unique and sorted elements and converted back into a list:

mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));

If you want to run that potentially in parallel, you can create a Stream pipeline by getting the entrySet() and calling parallelStream() on it. But then, you need to make sure to use a map that supports concurrency for mapGlobal, like a ConcurrentHashMap.

ConcurrentMap<String, List<String>> mapGlobal = new ConcurrentHashMap<>();
// ...
mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));
2 of 6
5

Using foreach over Map can be used to merge given arraylist.

    public Map<String, ArrayList<String>> merge(Map<String, ArrayList<String>> map1, Map<String, ArrayList<String>> map2) {
    Map<String, ArrayList<String>> map = new HashMap<>();
    map.putAll(map1);

    map2.forEach((key , value) -> {
        //Get the value for key in map.
        ArrayList<String> list = map.get(key);
        if (list == null) {
            map.put(key,value);
        }
        else {
            //Merge two list together
            ArrayList<String> mergedValue = new ArrayList<>(value);
            mergedValue.addAll(list);
            map.put(key , mergedValue);
        }
    });
    return map;
}
Find elsewhere
🌐
Javathinking
javathinking.com › blog › convert-2-list-to-map-java-8
Converting Two Lists to a Map in Java 8 | JavaThinking.com
July 21, 2025 - Lambda expressions are a concise way to represent anonymous functions in Java. They are used in conjunction with the Stream API to define operations on elements. For example, we can use a lambda expression to specify how to create a key - value pair from the elements of the two lists. Collectors are used to accumulate the elements of a stream into a final result, such as a map.
Top answer
1 of 3
1

Easiest way is to use Map to group by operators.Actually you can use Map instead of List but you can also iterate through map to append key and values and insert them back to the list. You can use the following code to achieve the result you want.

public static void main(String[] args) {
    List<Object> list1 = new ArrayList<Object>();
    list1.add("operator1, id1");
    list1.add("operator1, id2");
    list1.add("operator2, id3");
    list1.add("operator2, id4");
    list1.add("operator3, id5");
    list1.add("operator4, id6");

    List<Object> list2 = new ArrayList<Object>();
    list2.add("operator4, id7");
    list2.add("operator3, id8");
    list2.add("operator2, id9");
    list2.add("operator2, id10");
    list2.add("operator1, id11");
    list2.add("operator1, id12");

    Map<String, String> map = new HashMap<String, String>();
    List<Object> list3 = new ArrayList<Object>();

    Iterator<Object> it1 = list1.iterator();
    Iterator<Object> it2 = list2.iterator();

    while (it1.hasNext() && it2.hasNext()) {
        String[] line1 = ((String) it1.next()).split(",");
        map.put(line1[0], map.get(line1[0]) == null ? line1[1] : map.get(line1[0]) + ", " + line1[1]);

        String[] line2 = ((String) it2.next()).split(",");
        map.put(line2[0], map.get(line2[0]) == null ? line2[1] : map.get(line2[0]) + ", " + line2[1]);
    }

    for (Map.Entry<String, String> entry : map.entrySet()) {
        String item = entry.getKey() + "," + entry.getValue();
        System.out.println(item);
        list3.add(item);
    }
}

After running the code above the result will be :

operator4, id6,  id7
operator1, id1,  id2,  id11,  id12
operator3, id5,  id8
operator2, id3,  id4,  id9,  id10
2 of 3
1

Instead of List3 create a map as target source. Map will have operator as key and comma separated ids as value.

  • Read the content of list by iterating it.
  • Split the content with comma as a delimiter.
  • If operator is not present in map then add it else read the value, append the id and put it back in the map.
  • In the end it is just a matter of iterating the map to print what you need.
🌐
Coderanch
coderanch.com › t › 697498 › java › write-elegantly-merge-list-maps
how to write this more elegantly to merge a list of maps (Features new in Java 8 forum at Coderanch)
August 3, 2018 - Jeanne Boyarsky wrote:* This needs to be readable for my teammates who are less comfortable with advanced streams. Can you tell me in how far the java 8(+) streams and lambdas are used in practice, compared to the java < 8 ways? They are good with the basics: stream/filter/map/collect.
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.

🌐
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 - The code to do this is exactly easy: Map listsToMap(List keys, List values) { // check preconditions - sizes Map map = new HashMap (); ...
🌐
Baeldung
baeldung.com › home › java › java collections › java map › merging two maps with java
Merging Two Maps with Java | Baeldung
March 26, 2025 - Note that we have identical keys for the employee1 and employee5 entries in our maps, which we’ll use later. Java 8 adds a new merge() function into the java.util.Map interface.