我想为二元关系和传递关系定义优雅的接口。我将二元关系视为一组对,某个集合 X × Y 的子集。事实上,我打算主要使用传递关系,但偶尔需要一般的二元关系。这主要是为了我自己的使用,但我最终可能会将它作为一个 FLOSS 库发布给其他用户。我希望我的定义在一般层面上是有意义的,因为我对这些类的使用还没有精确的要求:我需要它们用于与科学研究相关的实验工作,我现在有一些想法,但还不清楚是什么样的在进行研究时,随着更多想法的出现,我将需要大量的实验。
大概的概念
我(认为我)需要的核心如下。
/**
* @param <F>
* the type used for the “from” elements.
* @param <T>
* the type used for the “to” elements.
*
*/
public interface BinaryRelationTentative<F, T> {
/**
* @return a view of the domain of this relation: all the elements x such that for some y, (x, y) is in the
* relation.
*/
public Set<F> getFromSet();
/**
* @return a view of the range of this relation: all the elements y such that for some x, (x, y) is in the relation.
*/
public Set<T> getToSet();
/**
* @return the number of pairs that this relation contains.
*/
public int size();
/**
* @return <code>true</code> iff the relation has empty from and to sets.
*/
public boolean isEmpty();
/**
* A binary relation equals an other one iff they have equal from and to sets and for each (x, y) contained in one,
* (x, y) is contained in the other one.
*/
@Override
public boolean equals(Object obj);
/**
* @return whether the given <code>from</code> element is in relation with the <code>to</code> element.
*/
public boolean contains(F from, T to);
/**
* Optional operation.
*/
public boolean add(F from, T to);
}
(这只是核心特性,所以你明白我的意思——欢迎更好的遍历特性等等,见下文。)然后我会定义一个TransitiveRelation<E>
extends BinaryRelation<E, E>
,它不实现add
而是提供addTransitive(F from, T to)
。
重用经典收藏
当然,现在我想尽可能地重用经典的集合接口。看来番石榴的SetMultimap
(javadoc,用户指南)具有我需要的核心功能等等。用户指南甚至提到了未标记有向图的用例。我看到直接使用的一个问题SetMultimap
是术语不完全正确:在二元关系的情况下谈论“键”和“值”很奇怪。此外,它遗漏了一些东西。在 SetMultimap(设计为从键到值)中存在一种有意义的不对称性,而在二元关系中则不太有意义。SetMultimap 有一个接口(和实现),它允许给定一个“from”元素,有效地迭代(即不遍历整个关系)通过与其相关的“to”元素。同样,我希望能够拥有一个“to”元素,有效地迭代相应的“from”元素。所以我需要一些可以称为 BiSetMultimap 的东西(对应于 aMap<K, Set<V>>
和 a Map<V, Set<K>>
)。我无法在 Java 世界中找到这样的东西。
因此,我目前正在考虑将其定义BinaryRelation<F, T>
为. 然后我可以在接口中创建更好命名的方法(在概念上等同于 中的方法),并且我可以添加一个提供“from”元素的方法。我可以提供基于两个保持同步的实现,一个代表关系,一个代表它的逆。SetMultimap<F, T>
SetMultimap
getInverselyRelated(T to): Set<F>
SetMultimap
这个问题有很多替代方法。例如,我可以定义BinaryRelation
为扩展SetMultimap
。或者我可以避免完全隐藏SetMultimap
并通过BinaryRelation#asSetMultimap()
. 这样我就得到了他们所有漂亮的方法接口。或者我可以完全放弃特定接口的想法并使用 aSetMultimap
而不是 a BinaryRelation
,然后考虑将反向遍历操作作为特定类中可用但不在接口级别上的优化功能。或者我也许可以使用 SetMultimap 以外的其他东西作为设计的基础。
因此,我的问题(终于!):您如何看待我的方法?你能想到其他方法吗?我忽略了一些问题?我可以使用的现有解决方案?
可能的链接
我考虑过使用一些图形库(JUNG、JGraphT、Blueprint),但我认为它们不符合我的需求。在我看来,所有这些都有一个Edge
增加复杂性的类(或 Edge 类型参数),并且没有一个提供像. 正如用户手册所说, Grph不提供顶点对象。我可能错过了一些东西,所以如果你不同意,请告诉我。SetMultimap
(编辑。)正如 Xaerxess 所提到的,这个番石榴问题建议将我在这里所说的 BiSetMultimap 添加到番石榴。