我需要重构下面的流代码:
List<Map<String, Integer>> list5 = new ArrayList<>();
map3 = new HashMap<>();
map3.put("foo", 1);
map3.put("bar", 2);
map3.put("zzz", 6);
list5.add(map3);
map3 = new HashMap<>();
map3.put("foo", 3);
map3.put("bar", 4);
map3.put("zzz", null);
list5.add(map3);
//new list with processed maps
List<Map<String, Integer>> list6 = list5.stream()
.map(hashmap -> {
Map<String, Integer> newMap = hashmap.entrySet().stream()
.collect(HashMap::new, (m, v) -> {
if (v.getKey().equals("bar")) {
m.put(v.getKey(), v.getValue() * 2);
} else {
m.put(v.getKey(), v.getValue());
}
}, HashMap::putAll);
return newMap;
})
.collect(toList());
System.out.println(list6);我需要一种仅从上面的流代码中提取/重构以下逻辑的方法,因为这部分将只更改我所拥有的其他映射列表:
if (v.getKey().equals("bar")) {
m.put(v.getKey(), v.getValue() * 2);
} else {
m.put(v.getKey(), v.getValue());
}使用IntelliJ,它向main()本身添加了一个双求和器,这在这里是不需要的,并删除了代码。我需要一种单独提取它的方法,如下所示:
List<Map<String, Integer>> list6 = list5.stream()
.map(hashmap -> {
Map<String, Integer> newMap = hashmap.entrySet().stream()
.collect(HashMap::new, (m, v) -> {
biconsumerLogic1.accept(m, v);
}, HashMap::putAll);
return newMap;
})
.collect(toList());biconsumerLogic1是一个独立的功能接口,如下所示:
BiConsumer biconsumerLogic1() {
accept(m, v) {
//logic goes here...
}
}我怎样才能做到这一点?任何指点都会受到赞赏。
谢谢..
发布于 2018-02-01 20:33:22
下面是我使用BiConsumers进行重构的版本:
psv main(...) {
List<Map<String, Integer>> newList = processMapData(origList, accumulator());
System.out.println(newList);
}
private static List<Map<String, Integer>> processMapData(List<Map<String, Integer>> origList, BiConsumer<HashMap<String, Integer>, Map.Entry<String, Integer>> accumulator) {
return origList.stream()
.map(hashmap -> {
Map<String, Integer> newMap = hashmap.entrySet().stream()
.collect(HashMap::new, accumulator, HashMap::putAll);
return newMap;
})
.collect(toList());
}
private static BiConsumer<HashMap<String, Integer>, Map.Entry<String, Integer>> accumulator() {
return (m, v) -> {
m.put(v.getKey(), v.getKey().equals("bar") ? v.getValue() * 2: v.getValue());
};
}我可以利用更多的控制,并将累加器动态注入到processMapData函数中。感谢@Federico的BiConsumer函数建议。
发布于 2018-02-01 15:41:31
看,问题在于使用流的问题。你已经过度设计了,你不需要它的大部分。
看:
List<Map<String, Integer>> newList = new ArrayList<>(list);
newList.replaceAll(eachMap -> {
Map<String, Integer> map = new HashMap<>(eachMap);
map.computeIfPresent("bar", (k,v) -> v * 2);
return map;
});要替换这个动作,你需要做这样的事情:
BiFunction<String, Integer, Integer> action = (k,v) -> v * 2;
newList.replaceAll(eachMap -> {
Map<String, Integer> map = new HashMap<>(eachMap);
map.computeIfPresent("bar", action);
return map;
});现在,您可以将整个过程提取到一个单独的方法中,并接受list和action (也可能是"bar"变量)作为参数,这里有您的值替换器。
发布于 2018-02-01 15:27:34
不如:
list5.stream().forEach(map -> map.replaceAll((k,v) -> k.equals("bar") ? v * 2 : v));这将对值进行就地替换。
如果你绝对需要一张新地图:
list6 = list5.stream()
.map(m -> m.entrySet().stream()
.collect(toMap(Map.Entry::getKey, e -> e.getValue() * (e.getKey().equals("bar") ? 2 : 1))))
.collect(toList());如果您希望重构,有两个选项:
备选案文1:
创建一个BiFunction,如:
public static BiFunction<String, Integer, Integer> valueCalculator() {
return (k,v) -> k.equals("bar") ? v * 2 : v;
}并使用:
list5.stream().forEach(map -> map.replaceAll(valueCalculator()));备选案文2:
创建一个方法:
public Integer valueCalculator(String key, Integer value) {
return key.equals("bar") ? value * 2 : value;
}使用方法引用
list5.stream().forEach(map -> map.replaceAll(this::valueCalculator));如果它是static方法,则为:
list5.stream().forEach(map -> map.replaceAll(MyClass::valueCalculator));我更喜欢选项2,因为它更容易理解、测试和调试。
https://stackoverflow.com/questions/48566208
复制相似问题