鉴于您提到重点是速度,这实际上归结为您需要如何访问数据,即您需要对数据结构提出什么问题。
例如,如果您只需要问“X 是否知道 Y”或“Y 是否知道 X”这样的问题,那么您只需要一个哈希映射。或哈希集,
只要您可以为它们中的一对生成一个像样的 hashCode() 实现
(请参阅前面的示例 hashCode 实现,虽然可能不是一个好的实现,而且我已经有很多年没有使用 Java 了)
即有一套
class Item extends Pair {
Item(A,B)
// override hashCode() and equals() methods as necessary
}
hashset<Item> relationships;
relationships.add(new Item(A,B))
relationships.add(new Item(B,C))
if( ! relationship.contains (new Item(B,A)))
// print "b does not know a"
或地图:
HashMap<Item,Boolean> relationships;
relationships.put(Item(A,B),True)
....
但是,如果您需要查看一个实体,然后找到它所知道的所有内容,那么图结构会更好。
如果您正在构建一个不需要太多灵活性的一次性数据集,您可以将图形实现为单个链表,包含从起点开始的所有边,并有一个哈希(按对象键)指向到每个已知项目列表的第一条边。
例如,未经测试的伪代码,不正确的java
Class Item {
Entity first
Entity second
Item next;
Item prior;
Item(x,y) { first = x; second = y; }
Item Join(nextItem) {
next = nextItem; next.prior = this; return next;
}
// override hashCode and equals() but don't use 'next' or prior as part of the hash calculation or equals comparison
//this is just for example, not sure if this is a good hash
long hashCode() { return a. hashCode() & b.hashCode(); }
}
class Graph extends HashSet<Item> {
Bool containsRelationship(Entity x, Entity y) {
return contains(new Item(x,y))
}
Bool isRcognisedEntity(Entity x) {
return contains(new Item(x,x))
}
Item getRelationships(Entity x) {
Item ret = get(new Item(x,x))
if ret is not null
return ret.next // return the first entity x knows, other than itself
else
return null // nothing known
}
Item addEntity(Entity e, Entity[] e_knows) {
Item first = new item (e,e)
add(first)
Item lastItem = first
for k in e_knows
lastItem = lastItem.join(new item(e,k))
add(lastItem)
return first
}
}
Entity a;
Entity b;
Entity c;
Graph g;
g.addEntity(a, {b,c})
g.addEntity(b, {c})
g.addEntity(c,{ a,b,c})
if g.contains(item(a,b))
Print "a knows b"
c_knows = g.getRelationships(c)
while c_knows is not null
Print "c knows " + c_knows.second
c_knows = c.next
所以你只用一个集合就可以看到这种方式,你可以问“x 知道 y”和“x 知道谁”,代价是下一个/先前属性的一些内存开销(你可能只需要一个)
如果您有两个单独的 A 和 B 类而不是一个通用的 Entity 基类,那么您可以使用 Object 来执行此操作,并根据需要在 Graph 类的例程中转换结果以提供类型安全。
例如
class Item {
Object first;
Object second;
...
}
class Graph {
// as above except use Object instead of Entity, and make the methods protected not public
}
class ABGraph extends Graph {
Iterator getRelationships(A a) {
return new B_Itemterator(super.getRelationships(a));
}
void addRelationships(A a,B[] b_knows) {
super.getRelationships( a, b_knows)
}
// Similar functions for B
}
class A_ItemIterator implements Java.collections...Iterator<A> {
A_ItemIterator(Item i) { this.i = I }
bool hasNext() { return i.next != null; }
A next() { item n = i.next; I = n; return n; }
}
// similar iterator class for B_ItemIterator
ABGraph g;
A a;
B b1;
B b2;
g.addRelationships(a, new B[]{b1,b2})
if g.contains (a,b1) // should still work
Iterator<B> i= g.getRelationships(a)
while(i.hasNext())
print " thing "+ a + " of type A knows about " + b.next() + "of type B'