Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to combine two lists into a map (Java)?

It would be nice to use for (String item: list), but it will only iterate through one list, and you'd need an explicit iterator for the other list. Or, you could use an explicit iterator for both.

Here's an example of the problem, and a solution using an indexed for loop instead:

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);   } } 

Output:

{apple=123, orange=456, pear=789} 

Is there a clearer way? Maybe in the collections API somewhere?

like image 505
13ren Avatar asked Dec 03 '09 12:12

13ren


People also ask

Which method is used to merge two lists?

The addAll() method to merge two lists The addAll() method is the simplest and most common way to merge two lists.


1 Answers

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.

like image 135
DrGodCarl Avatar answered Oct 09 '22 23:10

DrGodCarl