Java 8加入了两个地图列表

时间:2017-01-17 13:59:54

标签: java dictionary join merge java-stream

Java8中是否有任何方法可以使用Streams API连接两个地图列表? 让我们说我有:

列表#1

[  
   {  
      id=1, attr1='a', attr2='b'
   },
   {  
      id=2, attr1='c', attr2='d'
   },
   {  
      id=3, attr1='e', attr2='f'
   }
]

列表#2

[  
       {  
          id=1, attr3='x', attr4='y'
       },
       {  
          id=2, attr3='x', attr4='z'
       },
       {  
          id=3, attr3='z', attr4='y'
       }
    ]

现在我想通过密钥ID加入这两个列表(只列出一个SQL连接), 输出将是:

[  
       {  
          id=1, attr1='a', attr2='b', attr3='x', attr4='y'
       },
       {  
          id=2, attr1='c', attr2='d', attr3='x', attr4='z'
       },
       {  
          id=3, attr1='e', attr2='f', attr3='z', attr4='y'
       }
    ]

非常感谢!

3 个答案:

答案 0 :(得分:3)

final List<HashMap<String, String>> joinedById = list1.stream()
            .flatMap(m1 -> list2.stream()
                    .filter(y -> m1.get("id").equals(y.get("id")))
                    .map(m2 -> new HashMap<String, String>() {{
                        putAll(m1);
                        putAll(m2);
                    }}))
            .collect(Collectors.toList());

答案 1 :(得分:0)

有很多种方式,无论是否有流。最好的方法取决于您没有给我们的更准确的输入要求。以下内容适用于您的问题中的示例列表:

    if (list1.size() != list2.size()) {
        throw new IllegalStateException("Lists don’t match, not same size");
    }

    List<Map<String, Character>> comnbinedList = IntStream.range(0, list1.size())
            .mapToObj(i -> {
                    Map<String, Character> m1 = list1.get(i);
                    Character id1 = m1.get("id");
                    Map<String, Character> m2 = list2.get(i);
                    Character id2 = m1.get("id");
                    if (! id1.equals(id2)) {
                        throw new IllegalStateException("Lists don’t match, id " + id1 + " != " + id2);
                    }
                    HashMap<String, Character> mergedMap = new HashMap<>(m1);
                    mergedMap.putAll(m2);
                    return mergedMap; 
                })
            .collect(Collectors.toList());

结果是:

[{id=1, attr2=b, attr1=a, attr4=y, attr3=x}, {id=2, attr2=d, attr1=c, attr4=z, attr3=x}, {id=3, attr2=f, attr1=e, attr4=y, attr3=z}]

当然,您需要声明"id"一个常量。

答案 2 :(得分:0)

您在地图中使用ID键的数据结构;有点让这有点不寻常,但这是一个流收集器的例子。由于您的地图值均为intString,因此我使用了Map<String, Object>

import java.util.*;
public class JoinTwoListofMaps {
    public static void main(String... args){
        List<Map<String, Object>> list1 = new ArrayList<>();
        List<Map<String, Object>> list2 = new ArrayList<>();
        Map<String, Object> map1_1 = new HashMap<>();
            map1_1.put("id",1);
            map1_1.put("attr1","a");
            map1_1.put("attr2","b");
        list1.add(map1_1);
        Map<String, Object> map2_1 = new HashMap<>();
            map2_1.put("id",1);
            map2_1.put("attr3","x");
            map2_1.put("attr4","y");
        list2.add(map2_1);
        System.out.println(joinTwoListOfMaps(list1, list2));
    }
    @SafeVarargs
    public static List<Map<String, Object>> joinTwoListOfMaps(List<Map<String, Object>>... listsOfMaps){
        List<Map<String, Object>> finalList = Arrays.stream(listsOfMaps).collect(ArrayList::new, List::addAll, List::addAll);
        return finalList.stream().collect(ArrayList::new, (list, mapToMerge) ->{
            Optional<Map<String, Object>> mapWithSameID = list.stream()
                    .filter(map -> map.get("id").equals(mapToMerge.get("id"))).findFirst();
            if (mapWithSameID.isPresent()) mapWithSameID.get().putAll(mapToMerge);
            else list.add(mapToMerge);
        }, ArrayList::addAll);
    }
}