我需要重构我的下面的流代码:
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...
}
}
我如何实现这一目标?任何指针都表示赞赏。
谢谢..
答案 0 :(得分:3)
看,问题在于使用流。你已经过度设计了,你不需要大部分。
查找
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"
(可能还有{{1}}变量)作为参数,这里您有值替换器。
答案 1 :(得分:2)
我认为有更好的方法来做你实际做的事情。但严格回答如何提取和重构指定的代码,您可以这样做:
static <K, V> List<Map<K, V>> process(
List<Map<K, V>> source,
BiConsumer<? super Map<K, V>, ? super Map.Entry<K, V>> accumulator) {
return source.stream()
.map(m -> m.entrySet().stream()
.collect(HashMap::new, accumulator, Map::putAll))
.collect(Collectors.toList());
}
用法:
List<Map<String, Integer>> list6 = process(
list5,
(m, e) -> m.put(
e.getKey(),
e.getKey().equals("bar") ? e.getValue() * 2 : e.getValue()));
答案 2 :(得分:2)
以下是我使用BiConsumers重构的版本:
Cars Inspected =
VAR selectedMonth = MONTH(MAX('All Cars Inspected'[Workday]))
RETURN LOOKUPVALUE(Targets[Target],
Targets[Location], "Texas",
Targets[Description], "CarsInspected",
Targets[sMonth], selectedMonth)
我可以利用更多控制并动态地将累加器注入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());
};
}
函数。
感谢@Federico提供的BiConsumer功能建议。
答案 3 :(得分:1)
怎么样:
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());
如果您正在寻求重构,有两种选择:
创建BiFunction
,例如:
public static BiFunction<String, Integer, Integer> valueCalculator() {
return (k,v) -> k.equals("bar") ? v * 2 : v;
}
并使用:
list5.stream().forEach(map -> map.replaceAll(valueCalculator()));
创建方法:
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,因为它更容易理解,测试和调试。