我们知道Map接口对数学中的函数抽象进行建模。我应该如何对多变量函数建模?例如,对于模型f(x,y,z),我有两个选择:
Map<List<Integer>, Integer> f1;或
Map<Integer, Map<Integer, Map<Integer, Integer>>> f2;你认为哪一个更好?
谢谢,
发布于 2009-07-12 01:44:12
都不是。
你要找的技术叫做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(); }您可以对三元组或任意大小的元组执行相同的操作。但是要注意,因为这样的推理会导致异类列表,这就是aren't pretty in Java。
此外,您的Map表示只适用于部分函数。更重要的是,JDK的Map接口被设计为可变的,谁听说过可变函数呢?下面是一个更好的表示:
interface F<A, B> { public B apply(A a); }发布于 2009-07-12 01:02:53
第三个选项是定义一个简单的类,其中包含三个Integer字段x、y和z (例如,将其称为Triple ),并使用Map<Triple, Integer>。
如果你经常需要这样的东西,你可以使Triple本身泛型,并使用Map<Triple<Integer>, Integer> (或者如果你的一些“函数”需要不同类型的参数,它甚至可以是一个Map<Triple<Integer, Integer, Integer>, Integer>,但这开始失去可读性)。
发布于 2009-08-02 13:48:47
你的第一选择通常更好,因为它需要更少的内存和更少的代码来访问:
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();https://stackoverflow.com/questions/1115052
复制相似问题