二进制关系的java接口
我想为二元关系和传递关系定义优雅的接口。我认为二元关系是一组对,一组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);
}
(这只是核心特性,因此您可以理解我的意思-更好的遍历等特性是受欢迎的,请参见下文。)然后我将定义一个扩展BinaryRelation<E, E>
的TransitiveRelation<E>
,它不实现add
,而是提供addTransitive(F from, T to)
重复使用经典藏品
当然,我希望尽可能地重用经典集合接口。看起来番石榴的SetMultimap
(javadoc,user guide)具有我需要的核心功能和更多功能。用户指南甚至提到了未标记有向图的用例。我看到直接使用SetMultimap
的一个问题是术语并不完全正确:在二进制关系中提到“键”和“值”是很奇怪的。此外,它还遗漏了一些东西。在SetMultimap(设计为从键到值)中存在一种不对称性,而在二进制关系中则没有这种不对称性。SetMultimap有一个接口(和实现),它允许给定一个“from”元素,通过与之相关的“to”元素高效地迭代(即不遍历整个关系)。类似地,我希望能够使用“to”元素,高效地迭代相应的“from”元素。所以我需要一个叫做BiSetMultimap的东西(对应于aMap<K, Set<V>>
和aMap<V, Set<K>>
)。我在Java世界中还没有找到这样的东西
因此,我目前正在考虑将BinaryRelation<F, T>
定义为facade到SetMultimap<F, T>
。然后,我可以在接口中创建更好的命名方法(概念上等同于SetMultimap
中的方法),并且可以添加一个方法getInverselyRelated(T to): Set<F>
,该方法给出“from”元素。我可以提供基于两个保持同步的SetMultimap
的实现,一个表示关系,另一个表示其逆关系
对于这个问题有很多替代方法。例如,我可以将BinaryRelation
定义为扩展SetMultimap
。或者我可以避免完全隐藏SetMultimap
,并通过BinaryRelation#asSetMultimap()
提供对它的访问。这样我就得到了他们所有漂亮的方法接口。或者我可以完全放弃特定接口的想法,使用SetMultimap
而不是BinaryRelation
,然后将反向遍历操作视为特定类中可用的优化功能,但不在接口级别。或者我可以使用SetMultimap以外的其他东西作为设计的基础
因此,我的问题(最后!):你觉得我的方法怎么样?你能考虑其他方法吗?我忽略了一些问题?我可以使用的现有解决方案
可能的联系
我曾考虑使用一些图形库(JUNG、JGraphT、Blueprint),但我认为它们不适合我的需要。所有这些都有一个Edge
类(或边缘类型参数),这增加了复杂性,在我看来,没有一个提供的接口和实现比SetMultimap
更好Grph并不像user manual所说的那样,为顶点提供对象。我可能错过了一些东西,如果你不同意,请告诉我
(编辑)正如Xaerxess所提到的,这个番石榴issue建议在番石榴上添加我在这里称之为BiSetMultimap的东西
# 1 楼答案
听起来像是早期优化:为什么不在内部使用两个数据结构(问题中提到的
Map<K, Set<V>>
和Map<V, Set<K>>
)。当有最直接的方法存在实际问题时,你可以考虑不知名的图书馆或番石榴,但同时你可以在工作的其他方面取得进展。毕竟,接口的主要目的是隐藏底层实现,以便以后可以对其进行更改