【发布时间】:2021-02-21 12:27:28
【问题描述】:
对不起,我认为我写的标题不正确,并且很好地解释了我的要求,但目前我还没有找到更好的标题
我正在尝试将我的方法从 Java 中的命令式编程更改为函数式编程,有时很容易,但在其他情况下并不多……但我不会放弃 :)
我有一个值的映射,应该减少一个函数计算的数量,对于每个输入,都有一个或多个可以应用的函数,前一个函数减少的值对下一个函数,就是这样的
Map<String, Double> input = new HashMap<>() {{
put("IN1", 100.0);
put("IN2", 10.0);
}};
Map<String, List<Function<Double, Double>>> rules = Map.of(
"IN1", List.of(value -> value / 10.0, value -> 80.0, value -> 10.0),
"IN2", List.of(value -> 2.0),
"IN3", List.of(value -> value / 5.0));
在命令式“风格”中,我使用类似的函数解决了这个问题
for (Map.Entry<String, List<Function<Double, Double>>> entry : rules.entrySet()) {
String inName = entry.getKey();
Double inValue = input.get(inName);
if (inValue==null) continue;
for (Function<Double, Double> function : entry.getValue()) {
inValue -= function.apply(inValue);
if (inValue <= 0F) break;
}
input.put(inName, inValue);
}
函数式编程的正确方法应该是什么?
提前致谢:)
编辑
我找到的唯一解决方案如下
Map<String, Double> result =
input.entrySet().stream()
.map(e -> calculator(e, rules.get(e.getKey())))
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
第一步是按输入聚合所有规则,然后对每个输入进行迭代,并使用递归计算器函数创建另一个映射,该映射将为每个输入包含函数应用后的剩余值
private static Pair<String, Double> calculator(Map.Entry<String, Double> input, List<Function<Double, Double>> entries) {
double value = input.getValue();
double result = calculator(value, entries.iterator());
return Pair.of(input.getKey(), result);
}
private static double calculator(double value, Iterator<Function<Double, Double>> iterator) {
if (!iterator.hasNext() || value<=0F) return value;
Function<Double, Double> function = iterator.next();
double cost = function.apply(value);
return calculator(value-cost, iterator);
}
计算器是一个递归函数,所以遵守不变性规则:)
如果存在其他解决方案,请告诉我!
提前致谢
【问题讨论】:
-
FP 环境通常提供具有“修饰符”的“持久”数据结构,这些“修饰符”不会更改原始数据但返回修改后的副本。对于地图,这意味着拥有
newMap = map.updated(key, newValue)。但是,如果您没有支持它的专用数据结构,这可能会非常低效。例如,复制一个完整的 hashmap 并不好。 -
谢谢 Thilo,你是对的,我目前找到的唯一解决方案是使用收集器重建另一张地图,但我希望这不是唯一的解决方案,因为在这种情况下我不得不反复更新地图,这不是一个好的解决方案恕我直言:)
-
你为什么不定义第二张地图说
resultMap。如果密钥在resultMap-> 计算,如果不是从inputMap获取密钥-> 计算。无论哪种情况,结果都会发送到resultMap。 -
谢谢卡普兰,或多或少,这是我的第一个解决方案,创建第二张地图,通过收藏家更新,但在这种情况下,我们正在更改一个对象......现在我正在为另一个解决办法,我一会儿贴出答案
标签: java functional-programming