使用 Java 8 流处理地图列表

新手上路,请多包涵

如何将此代码简化为单个 lambda 表达式?这个想法是有一个地图列表,我想创建一个新的地图列表,使用键上的过滤器。在这个例子中,我想重新映射它,以便它只保留键“x”和“z”。

     Map<String, String> m0 = new LinkedHashMap<>();
    m0.put("x", "123");
    m0.put("y", "456");
    m0.put("z", "789");

    Map<String, String> m1 = new LinkedHashMap<>();
    m1.put("x", "000");
    m1.put("y", "111");
    m1.put("z", "222");

    List<Map> l = new ArrayList<>(Arrays.asList(m0, m1));
    List<Map> tx = new ArrayList<>();
    for(Map<String, String> m : l) {
        Map<String, String> filtered = m.entrySet()
                .stream()
                .filter(map -> map.getKey().equals("x") || map.getKey().equals("z"))
                .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
        tx.add(filtered);
    }
    System.err.println("l: " + l);
    System.err.println("tx: " + tx);

输出:

     l: [{x=123, y=456, z=789}, {x=000, y=111, z=222}]
    tx: [{x=123, z=789}, {x=000, z=222}]

原文由 user3892260 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 428
2 个回答

当然,您可以将整个操作转换为一个 Stream 操作。

 // no need to copy a List (result of Array.asList) to an ArrayList, by the way
List<Map<String, String>> l = Arrays.asList(m0, m1);

List<Map<String, String>> tx = l.stream().map(m -> m.entrySet().stream()
        .filter(map -> map.getKey().equals("x") || map.getKey().equals("z"))
        .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())))
    .collect(Collectors.toList());

但请注意,流过 Map 和过滤是一个具有线性时间复杂度的操作,因为它会根据过滤器检查每个映射的每个键,而你只有很少数量的实际键你想要保留。所以在这里,使用起来更简单、更有效(对于更大的地图)

 List<Map<String, String>> tx = l.stream()
    .map(m -> Stream.of("x", "y")
                    .filter(m::containsKey).collect(Collectors.toMap(key->key, m::get)))
    .collect(Collectors.toList());

每个地图只会执行四次查找。如果它困扰你,你甚至可以将它减少到两次查找,但是,常数因子与整体时间复杂度无关,如果地图具有恒定时间查找,则整体时间复杂度将是恒定时间,例如 HashMap .即使对于具有 O(log(n)) 查找时间复杂度的地图,如 TreeMap ,如果地图大于示例代码的三个映射,这将比线性扫描更有效。

原文由 Holger 发布,翻译遵循 CC BY-SA 3.0 许可协议

你可以尝试这样的事情:

 List<Map<String, String>> l = Arrays.asList(m0, m1);

l.forEach(map -> {
    map.entrySet().removeIf(e -> !e.getKey().equals("x") && !e.getKey().equals("z"));
});

如果输入键不是 xz ,它只是删除每个 Map<String, String> 中的所有映射。

编辑:您应该使用 Radiodef 的等效但更短的方法!

 List<Map<String, String>> l = Arrays.asList(m0, m1);

l.forEach(map -> map.keySet().retainAll(Arrays.asList("x", "z"));

原文由 Jacob G. 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题