Tin
Tin

Reputation: 804

Java 8: Convert 2 Lists into List of Map

What I have: (2 lists)

List<String> keys = Arrays.asList("1", "2", "3");
List<String[]> values = Arrays.asList("a,aa,aaa".split(","), "b,bb,bbb".split(","));

What I'm trying to get: (list of map)

[
    {"1": "a", "2": "aa", "3": "aaa"},
    {"1": "b", "2": "bb", "3": "bbb"}
]

Java 7 Solution:

List<Map<String,String>> list = new LinkedList<Map<String,String>>();
for(String[] vs: values) {
    Map<String, String> map = new LinkedHashMap<String, String>();
    for(int i = 0; i < keys.size(); i++) {
        map.put(keys.get(i), vs[i]);
    }
    list.add(map);
}

I'm learning Java 8 and steam. I wonder if it's possible to do it cleaner.

Upvotes: 3

Views: 1483

Answers (2)

Pratik Pawar
Pratik Pawar

Reputation: 91

Please find below two ways to achieve this using java 8 stream:

List values =Arrays.asList("a,aa,aaa".split(","), "b,bb,bbb".split(","));

      List<Map<String, String>> maps= values.stream().map(l-> IntStream.range(0, l.length).boxed().collect(Collectors.toMap(i-> String.valueOf(i+1), j-> l[j]))).collect(Collectors.toList());
      System.out.println("Printing list of map using boxed"+ maps);

      List<Map<String, String>> maps2= values.stream().map(l-> IntStream.range(0, l.length).mapToObj(a-> Integer.valueOf(a)).collect(Collectors.toMap(i-> String.valueOf(i+1), j-> l[j]))).collect(Collectors.toList());
      System.out.println("Printing list of map using maptoObject"+ maps2);

Upvotes: 0

shmosel
shmosel

Reputation: 50716

One approach is to iterate over values and then iterate over the indexes of each array, matching them to the corresponding index in keys:

List<Map<String, String>> maps = values.stream()
        .map(a -> IntStream.range(0, keys.size())
                .boxed()
                .collect(Collectors.toMap(keys::get, i -> a[i])))
        .collect(Collectors.toList());

The intermediate boxing is unfortunately necessary in order to use the toMap() collector. If you want to avoid the overhead of boxed indexing, you can define a custom collector in the inner stream:

IntStream.range(0, keys.size())
    .collect(HashMap<String, String>::new,
        (m, i) -> m.put(keys.get(i), a[i]),
        HashMap::putAll)

Upvotes: 2

Related Questions