简体   繁体   English

Java:加入两个Map列表 <String, Object> 使用流

[英]Java: join two lists of Map<String, Object> using Stream

I have two lists of Map<String, Object> as shown below: 我有两个Map<String, Object> ,如下所示:

List1=[ {ID=1, actor="A", film="AA"}, 
        {ID=1, actor="B", film="AA"} ]

List2={ [ID = 1, director="C"] } 

Result = { [ID=1, actor="A", film="AA", director="C"], 
           [ID=1, actor="B", film="AA", director="C"] }

I want to use the Stream class in Java 8 to join these lists. 我想使用Java 8中的Stream类来加入这些列表。

How do I join the to get the value of Result shown? 如何加入以获得显示的结果值?

Is the Stream class in Java 8 fast and stable if List1 and List2 are very big? 如果List1List2非常大,Java 8中的Stream类是否快速且稳定?

Ah now I understand what you want :) I don't know if there is a better way with streams but here is a solution which would work. 嗯,现在我明白了您想要的是什么:)我不知道流中是否有更好的方法,但是这里有一个可行的解决方案。

List<Map<String, String>> resultList = l1.stream()
        .map(m1 -> {
           Map<String, String> map = new HashMap<>();
           map.putAll(m1);
           l2.stream()
               .filter(m2 -> map.get("ID").equals(m2.get("ID")))
               .findFirst()
               .ifPresent(m2 -> map.put("director", m2.get("director")));
           return map;
        })
        .collect(Collectors.toList());

The above code generates a new List resultList and does not modify the other lists List1 and List2 . 上面的代码生成一个新的List resultList ,而不修改其他列表List1List2 If it does not matter if List1 gets modified or not you could do it in a cleaner, more readable way. 如果List1被修改没关系,您可以以一种更简洁,更易读的方式进行操作。

l1.forEach(m1 -> l2.stream()
    .filter(m2 -> m1.get("ID").equals(m2.get("ID")))
    .findFirst()
    .ifPresent(m2 -> m1.putIfAbsent("director", m2.get("director"))));

This way the entries of list1 get modified. 这样, list1的条目将被修改。 So with the above example list1 is becomes the joined list . 因此,在上面的示例中, list1成为joined list But it's actually good practice to have methods without any side effects. 但是,拥有没有任何副作用的方法实际上是一个好习惯。 So I would not prefer the above example. 所以我不希望上面的例子。

I would recommend a method getJoinedList which returns a new List and does not modify the other lists. 我建议使用方法getJoinedList ,该方法返回一个新列表,并且不修改其他列表。 And in this case I would not use streams but the old-fashioned for-loop. 在这种情况下,我不会使用streams而是使用老式的for循环。

private static List<Map<String, String>> getJoinedList(
    List<Map<String, String>> l1, List<Map<String, String>> l2) {

    List<Map<String, String>> result = new ArrayList<>();
    for (Map<String, String> m1 : l1) {
        Map<String, String> newMap = new HashMap<>();
        newMap.putAll(m1);
        for (Map<String, String> m2 : l2) {
            if (m1.get("ID").equals(m2.get("ID"))) {
                newMap.put("director", m2.get("director"));
                break;
            }
        }
        result.add(newMap);
    }

    return result;
}

Then you just can call the method like this. 然后,您可以调用这样的方法。

List<Map<String, String>> joinedList = getJoinedList(l1, l2);

If performance matters, you should first build an index of directors: 如果绩效很重要,则应首先建立一个董事索引:

Map<Object, Object> directors = list2.stream()
    .collect(Collectors.toMap(m -> m.get("ID"), m -> m.get("director")));

Then you can merge the directors to the list entries easily: 然后,您可以轻松地将导演合并到列表条目中:

list1.stream().forEach(m -> m.put("director", directors.get(m.get("ID"))));

Accesing the director via a Map will be faster than searching the director for each list entry. 通过Map访问导演比在导演中搜索每个列表条目更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM