Как мне моделировать многопараметрическую функцию? - PullRequest
2 голосов
/ 12 июля 2009

Мы знаем, что модели интерфейса карты функционируют как абстракция в математике. Как мне моделировать многопараметрическую функцию? Например, для модели f (x, y, z) у меня есть два варианта:

Map<List<Integer>, Integer> f1;

или

Map<Integer, Map<Integer, Map<Integer, Integer>>> f2;

Какой из них вы считаете лучше?

Спасибо

Ответы [ 3 ]

4 голосов
/ 12 июля 2009

Ни.

Техника, которую вы ищете, называется без присмотра . Мы знаем, что функция представляет логическое следствие:

∀ a b. a -> b

Мы также знаем, что если A и B подразумевают C, то A подразумевает, что B подразумевает C:

∀ a b c. ((a, b) => c) <=> (a => b => c)

Вот доказательство. Посмотрите на таблицу истинности для логического следствия, и вы увидите, что они эквивалентны. Итак, как вы представляете A and B на уровне типа? Вы используете тип продукта. Произведение двух типов представляет собой пару, то есть тип, значения которого имеют оба типа:

interface P2<A, B> { public A _1(); public B _2(); }

Вы можете сделать то же самое с тройками или кортежами любой арности. Однако будьте осторожны, так как эта линия рассуждений приводит вас к гетерогенным спискам, которые не очень красивы в Java .

Кроме того, ваше представление Map подходит только для частичных функций . Более того, интерфейс JDK Map разработан так, чтобы быть изменяемым , и кто бы ни слышал об изменяемой функции? Вот лучшее представление:

interface F<A, B> { public B apply(A a); }
3 голосов
/ 12 июля 2009

Третий вариант, который я бы предпочел, - это определить простой класс с тремя Integer полями x, y и z (например, назовем его Triple) и использовать Map<Triple, Integer> .

Если вам часто нужны такие вещи, вы можете сделать Triple сам по себе универсальным и использовать Map<Triple<Integer>, Integer> (или если некоторые из ваших «функций» должны иметь аргументы разных типов, это может быть даже Map<Triple<Integer, Integer, Integer>, Integer> но это начинает терять читабельность ИМХО).

0 голосов
/ 02 августа 2009

Ваш первый выбор обычно лучше, так как он требует меньше памяти и требует меньше кода для доступа:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...