我们知道Map接口模型在数学中具有抽象功能。我该如何建模多变量函数?例如,为了模拟f(x,y,z),我有两个选择:
Map<List<Integer>, Integer> f1;
或
Map<Integer, Map<Integer, Map<Integer, Integer>>> f2;
您认为哪一个更好?
谢谢,
答案 0 :(得分:4)
都不是。
您正在寻找的teqnique称为uncurrying。我们知道函数代表了逻辑含义:
∀ a b. a -> b
我们也知道如果A和B暗示C,则A暗示B暗示C:
∀ a b c. ((a, b) => c) <=> (a => b => c)
Here's proof.查看一个关于逻辑含义的真值表,你会发现它们是等价的。那么如何在类型级别表示A and B
?您使用的是产品类型。两种类型的乘积是一对,即其值具有两种类型的类型:
interface P2<A, B> { public A _1(); public B _2(); }
你可以用三元组或任何arity的元组做同样的事情。但请注意,因为这种推理会引导您进入异构列表,aren't pretty in Java。
此外,您的Map
表示仅适用于部分功能。更重要的是,JDK的Map
接口设计为可变,谁听说过可变功能?这是一个更好的代表:
interface F<A, B> { public B apply(A a); }
答案 1 :(得分:3)
我希望第三个选项是定义一个包含三个Integer
字段x
,y
和z
的简单类(称之为Triple
例如,并使用Map<Triple, Integer>
。
如果你经常需要这种东西,你可以使Triple
本身通用,并使用Map<Triple<Integer>, Integer>
(或者如果你的某些“函数”需要有不同类型的参数,它甚至可以一个Map<Triple<Integer, Integer, Integer>, Integer>
,但这开始失去可读性恕我直言。
答案 2 :(得分:0)
您的第一选择通常更好,因为它需要更少的内存并且需要更少的代码来访问:
Map<List<Integer>, Integer> f1 = ...
f1.put(Arrays.asList(1, 2, 3), 7);
Integer v = f1.get(Arrays.asList(1, 2, 3));
仅在访问模式需要时使用地图地图,例如
Map<Integer, Map<Integer, Map<Integer, Integer>>> f2 = ...
Set<Integer> keys = f2.keySet();