如何将此代码简化为单个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}]
答案 0 :(得分:11)
当然,您可以将整个操作转换为一个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
,如果地图大于示例代码的三个映射,这将比线性扫描更有效。
答案 1 :(得分:5)
您可以尝试这样的事情:
List<Map<String, String>> l = Arrays.asList(m0, m1);
l.forEach(map -> {
map.entrySet().removeIf(e -> !e.getKey().equals("x") && !e.getKey().equals("z"));
});
如果条目密钥不是Map<String, String>
或x
,它只会删除每个z
中的所有映射。
编辑:您应该使用Radiodef的等效但更短的方法!
List<Map<String, String>> l = Arrays.asList(m0, m1);
l.forEach(map -> map.keySet().retainAll(Arrays.asList("x", "z"));
答案 2 :(得分:2)
尝试以下代码(我声明了desiredKeys
的列表):
public class Main {
public static void main(String[] args) {
Map<String, String> m0 = new HashMap<>();
m0.put("x", "123");
m0.put("y", "456");
m0.put("z", "789");
Map<String, String> m1 = new HashMap<>();
m1.put("x", "000");
m1.put("y", "111");
m1.put("z", "222");
List<Map<String, String>> l = new ArrayList<>(Arrays.asList(m0, m1));
List<String> desiredKeys = Lists.newArrayList("x", "z");
List<Map<String, String>> transformed = l.stream().map(map -> map.entrySet().stream()
.filter(e -> desiredKeys.stream().anyMatch(k -> k.equals(e.getKey())))
.collect(Collectors.toMap(e -> e.getKey(), p -> p.getValue()))).filter(m -> !m.isEmpty()).collect(Collectors.toList());
System.err.println(l);
System.err.println(transformed);
}
}
答案 3 :(得分:1)
试试这个,它应该有效:
Map<String, String> m0 = new HashMap<>();
m0.put("x", "123");
m0.put("y", "456");
m0.put("z", "789");
Map<String, String> m1 = new HashMap<>();
m1.put("x", "000");
m1.put("y", "111");
m0.put("z", "222");
List<Map> l = new ArrayList<>(Arrays.asList(m0, m1));
List<Map> transformed = new ArrayList<Map>() ;
l.stream().map(map -> {
Set<String> keys = map.keySet() ;
Map<String, String> newMap = new HashMap<>();
for(String key : keys){
if(key.equals("x")|| key.equals("z"))
newMap.put(key, map.get(key).toString()) ;
}
return newMap ;
}).forEach(map -> transformed.add(map));
System.out.println(transformed);
答案 4 :(得分:1)
怎么样:
tx = StreamEx.of(l)
.map(m -> EntryStream.of(m).filterKeys(k -> k.equals("x") || k.equals("z")).toMap())
.toList();