4 package net
.kezvh
.collections
.graphs
.directed
;
6 import java
.util
.Collections
;
7 import java
.util
.HashMap
;
9 import java
.util
.NoSuchElementException
;
12 import net
.kezvh
.collections
.Pair
;
13 import net
.kezvh
.collections
.DualMap
.DualMap
;
14 import net
.kezvh
.collections
.DualMap
.HashDualMap
;
15 import net
.kezvh
.collections
.views
.MapAsView
;
16 import net
.kezvh
.collections
.views
.SetView
;
17 import net
.kezvh
.collections
.wrappers
.WrappedSet
;
18 import net
.kezvh
.functional
.lambda
.L1
;
20 import com
.google
.common
.collect
.AbstractMapEntry
;
23 * Nodes are tracked by a HashMap. Edges are tracked by a HashMap2. This gives
24 * O(1) performance for adding or querying anything.
27 * @param <Node> COMMENT
28 * @param <NodeValue> COMMENT
29 * @param <EdgeValue> COMMENT
31 public class HashDirectedGraph
<Node
, NodeValue
, EdgeValue
> extends HashMap
<Node
, NodeValue
> implements DirectedGraphWithValues
<Node
, NodeValue
, EdgeValue
> {
32 private final L1
<NodeValue
, Node
> getValue
= new L1
<NodeValue
, Node
>() {
33 public NodeValue
op(final Node param
) {
34 return HashDirectedGraph
.this.get(param
);
38 private final DualMap
<Node
, Node
, EdgeValue
> edges
= new HashDualMap
<Node
, Node
, EdgeValue
>();
39 private final L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, Map
.Entry
<Pair
<Node
, Node
>, EdgeValue
>> getEdges
= new L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, Map
.Entry
<Pair
<Node
, Node
>, EdgeValue
>>() {
41 * @see net.kezvh.functional.lambda.L1#op(java.lang.Object)
42 * @param param COMMENT
46 public EdgeWithValues
<Node
, NodeValue
, EdgeValue
> op(final Map
.Entry
<Pair
<Node
, Node
>, EdgeValue
> param
) {
47 return new EdgeWithValues
<Node
, NodeValue
, EdgeValue
>() {
49 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getDestination()
53 public java
.util
.Map
.Entry
<Node
, NodeValue
> getDestination() {
54 return new Map
.Entry
<Node
, NodeValue
>() {
56 * @see java.util.Map.Entry#getKey()
60 public Node
getKey() {
61 return param
.getKey().get2();
65 * @see java.util.Map.Entry#getValue()
69 public NodeValue
getValue() {
70 return HashDirectedGraph
.this.get(this.getKey());
73 public NodeValue
setValue(final NodeValue arg0
) {
74 return HashDirectedGraph
.this.put(this.getKey(), arg0
);
80 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getSource()
84 public java
.util
.Map
.Entry
<Node
, NodeValue
> getSource() {
85 return new Map
.Entry
<Node
, NodeValue
>() {
87 * @see java.util.Map.Entry#getKey()
91 public Node
getKey() {
92 return param
.getKey().get1();
96 * @see java.util.Map.Entry#getValue()
100 public NodeValue
getValue() {
101 return HashDirectedGraph
.this.get(this.getKey());
104 public NodeValue
setValue(final NodeValue arg0
) {
105 return HashDirectedGraph
.this.put(this.getKey(), arg0
);
111 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getValue()
115 public EdgeValue
getValue() {
116 return param
.getValue();
119 public EdgeValue
setValue(final EdgeValue newValue
) {
120 return param
.setValue(newValue
);
124 public Node
getDestinationNode() {
125 return param
.getKey().get2();
129 public Node
getSourceNode() {
130 return param
.getKey().get1();
136 private final L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, DualMap
.Entry
<Node
, Node
, EdgeValue
>> getEdges2
= new L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, DualMap
.Entry
<Node
, Node
, EdgeValue
>>() {
138 * @see net.kezvh.functional.lambda.L1#op(java.lang.Object)
139 * @param param COMMENT
143 public EdgeWithValues
<Node
, NodeValue
, EdgeValue
> op(final DualMap
.Entry
<Node
, Node
, EdgeValue
> param
) {
144 return new EdgeWithValues
<Node
, NodeValue
, EdgeValue
>() {
146 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getDestination()
150 public java
.util
.Map
.Entry
<Node
, NodeValue
> getDestination() {
151 return new Map
.Entry
<Node
, NodeValue
>() {
153 * @see java.util.Map.Entry#getKey()
157 public Node
getKey() {
158 return param
.getKey().get2();
162 * @see java.util.Map.Entry#getValue()
166 public NodeValue
getValue() {
167 return HashDirectedGraph
.this.get(this.getKey());
170 public NodeValue
setValue(final NodeValue arg0
) {
171 return HashDirectedGraph
.this.put(this.getKey(), arg0
);
177 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getSource()
181 public java
.util
.Map
.Entry
<Node
, NodeValue
> getSource() {
182 return new Map
.Entry
<Node
, NodeValue
>() {
184 * @see java.util.Map.Entry#getKey()
188 public Node
getKey() {
189 return param
.getKey().get1();
193 * @see java.util.Map.Entry#getValue()
197 public NodeValue
getValue() {
198 return HashDirectedGraph
.this.get(this.getKey());
201 public NodeValue
setValue(final NodeValue arg0
) {
202 return HashDirectedGraph
.this.put(this.getKey(), arg0
);
208 * @see net.kezvh.collections.graphs.directed.EdgeWithValues#getValue()
212 public EdgeValue
getValue() {
213 return param
.getValue();
216 public EdgeValue
setValue(final EdgeValue newValue
) {
217 return param
.setValue(newValue
);
221 public Node
getDestinationNode() {
222 return param
.getKey().get2();
226 public Node
getSourceNode() {
227 return param
.getKey().get1();
233 private final Set
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>> edgesSet
= new SetView
<Map
.Entry
<Pair
<Node
, Node
>, EdgeValue
>, EdgeWithValues
<Node
, NodeValue
, EdgeValue
>>(this.edges
.entrySet(), this.getEdges
) {
235 * @see java.util.AbstractCollection#remove(java.lang.Object)
239 @SuppressWarnings("unchecked")
241 public boolean remove(final Object o
) {
242 final EdgeWithValues
<Node
, NodeValue
, EdgeValue
> other
= (EdgeWithValues
<Node
, NodeValue
, EdgeValue
>) o
;
243 return HashDirectedGraph
.this.edges
.remove(other
.getSource().getKey(), other
.getDestination().getKey()) != null;
247 private void assertContains(final Object
... nodes
) {
248 for (final Object node
: nodes
)
249 if (!this.containsKey(node
))
250 throw new NoSuchElementException();
254 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#addEdge(java.lang.Object,
255 * java.lang.Object, java.lang.Object)
256 * @param source COMMENT
257 * @param destination COMMENT
258 * @param edgeValue COMMENT
262 public EdgeValue
addEdge(final Node source
, final Node destination
, final EdgeValue edgeValue
) {
263 this.assertContains(source
, destination
);
265 return this.edges
.put(source
, destination
, edgeValue
);
269 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#containsEdge(java.lang.Object,
271 * @param source COMMENT
272 * @param destination COMMENT
276 public boolean containsEdge(final Node source
, final Node destination
) {
277 this.assertContains(source
, destination
);
279 return this.edges
.containsKey(source
, destination
);
283 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#containsEdge(net.kezvh.collections.graphs.directed.Edge)
284 * @param edge COMMENT
288 public boolean containsEdge(final EdgeWithValues
<Node
, NodeValue
, EdgeValue
> edge
) {
289 return this.containsEdge(edge
.getSource().getKey(), edge
.getDestination().getKey());
293 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#edgeCount()
297 public long edgeCount() {
298 return this.edges
.size();
302 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#edges()
306 public Set
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>> edges() {
307 return this.edgesSet
;
311 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#getEdgeValue(java.lang.Object,
313 * @param source COMMENT
314 * @param destination COMMENT
318 public EdgeValue
getEdgeValue(final Node source
, final Node destination
) {
319 return this.edges
.get(source
, destination
);
323 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#inDegree(java.lang.Object)
324 * @param destination COMMENT
328 public int inDegree(final Node destination
) {
329 return this.edges
.entrySetOnKey2(destination
).size();
333 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#inEdgeSources(java.lang.Object)
334 * @param destination COMMENT
338 public Map
<Node
, NodeValue
> inEdgeSources(final Node destination
) {
339 return new MapAsView
<Node
, NodeValue
>(this.edges
.keySetOnKey2(destination
), this.getValue
);
343 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#inEdges(java.lang.Object)
344 * @param destination COMMENT
348 public Set
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>> inEdges(final Node destination
) {
349 return new SetView
<DualMap
.Entry
<Node
, Node
, EdgeValue
>, EdgeWithValues
<Node
, NodeValue
, EdgeValue
>>(this.edges
.entrySetOnKey2(destination
), this.getEdges2
);
353 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#outDegree(java.lang.Object)
354 * @param source COMMENT
358 public int outDegree(final Node source
) {
359 return this.edges
.entrySetOnKey1(source
).size();
363 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#outEdgeDestinations(java.lang.Object)
364 * @param source COMMENT
368 public Map
<Node
, NodeValue
> outEdgeDestinations(final Node source
) {
369 return new MapAsView
<Node
, NodeValue
>(this.edges
.keySetOnKey1(source
), this.getValue
);
373 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#outEdges(java.lang.Object)
374 * @param source COMMENT
378 public Set
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>> outEdges(final Node source
) {
379 return new SetView
<DualMap
.Entry
<Node
, Node
, EdgeValue
>, EdgeWithValues
<Node
, NodeValue
, EdgeValue
>>(this.edges
.entrySetOnKey1(source
), this.getEdges2
);
384 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#removeEdge(java.lang.Object,
386 * @param source COMMENT
387 * @param destination COMMENT
391 public EdgeValue
removeEdge(final Node source
, final Node destination
) {
392 return this.edges
.remove(source
, destination
);
396 * @see net.kezvh.collections.graphs.directed.DirectedGraphWithValues#removeEdge(net.kezvh.collections.graphs.directed.EdgeWithEdgeValue)
397 * @param edge COMMENT
401 public EdgeValue
removeEdge(final EdgeWithValues
<Node
, NodeValue
, EdgeValue
> edge
) {
402 return this.edges
.remove(edge
.getSourceNode(), edge
.getDestinationNode());
405 @SuppressWarnings("unchecked")
407 public NodeValue
remove(final Object key
) {
408 this.edges
.remove1((Node
) key
);
409 this.edges
.remove2((Node
) key
);
410 return super.remove(key
);
414 * @see java.util.Map#clear()
417 public void clear() {
423 public DirectedGraphWithEdgeValues
<Node
, EdgeValue
> keySet() {
427 private final KeySet keyset
= new KeySet();
429 private final class KeySet
extends WrappedSet
<Node
, Set
<Node
>> implements DirectedGraphWithEdgeValues
<Node
, EdgeValue
> {
432 super(HashDirectedGraph
.super.keySet());
436 public boolean containsEdge(final Node source
, final Node destination
) {
437 return HashDirectedGraph
.this.containsEdge(source
, destination
);
441 public long edgeCount() {
442 return HashDirectedGraph
.this.edgeCount();
446 public int inDegree(final Node destination
) {
447 return HashDirectedGraph
.this.inDegree(destination
);
451 public int outDegree(final Node source
) {
452 return HashDirectedGraph
.this.outDegree(source
);
456 public Set
<Node
> adjacentFrom(final Node source
) {
457 return HashDirectedGraph
.this.adjacentFrom(source
);
461 public Set
<Node
> adjacentTo(final Node destination
) {
462 return HashDirectedGraph
.this.adjacentTo(destination
);
466 public EdgeValue
addEdge(final Node source
, final Node destination
, final EdgeValue edgeValue
) {
467 return HashDirectedGraph
.this.addEdge(source
, destination
, edgeValue
);
471 public EdgeValue
getEdgeValue(final Node source
, final Node destination
) {
472 return HashDirectedGraph
.this.getEdgeValue(source
, destination
);
476 public EdgeValue
removeEdge(final Node source
, final Node destination
) {
477 return HashDirectedGraph
.this.removeEdge(source
, destination
);
481 public EdgeValue
removeEdge(final EdgeWithEdgeValue
<Node
, EdgeValue
> edge
) {
482 return HashDirectedGraph
.this.removeEdge(edge
.getSourceNode(), edge
.getDestinationNode());
486 public boolean containsEdge(final EdgeWithEdgeValue
<Node
, EdgeValue
> edge
) {
487 return HashDirectedGraph
.this.containsEdge(edge
.getSourceNode(), edge
.getDestinationNode());
490 private final L1
<EdgeWithEdgeValue
<Node
, EdgeValue
>, EdgeWithValues
<Node
, NodeValue
, EdgeValue
>> getSetEdges
= new L1
<EdgeWithEdgeValue
<Node
, EdgeValue
>, EdgeWithValues
<Node
, NodeValue
, EdgeValue
>>() {
492 public EdgeWithEdgeValue
<Node
, EdgeValue
> op(final EdgeWithValues
<Node
, NodeValue
, EdgeValue
> param
) {
493 return new EdgeWithEdgeValue
<Node
, EdgeValue
>() {
495 public Node
getDestinationNode() {
496 return param
.getDestinationNode();
500 public Node
getSourceNode() {
501 return param
.getSourceNode();
505 public EdgeValue
getValue() {
506 return param
.getValue();
509 public EdgeValue
setValue(final EdgeValue newValue
) {
510 return param
.setValue(newValue
);
516 private final L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, EdgeWithEdgeValue
<Node
, EdgeValue
>> inverseSetEdges
= new L1
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, EdgeWithEdgeValue
<Node
, EdgeValue
>>() {
518 public EdgeWithValues
<Node
, NodeValue
, EdgeValue
> op(final EdgeWithEdgeValue
<Node
, EdgeValue
> param
) {
519 return new EdgeWithValues
<Node
, NodeValue
, EdgeValue
>() {
521 public java
.util
.Map
.Entry
<Node
, NodeValue
> getDestination() {
522 return new AbstractMapEntry
<Node
, NodeValue
>() {
524 public Node
getKey() {
525 return getDestinationNode();
529 public NodeValue
getValue() {
530 return HashDirectedGraph
.this.get(this.getKey());
536 public Node
getDestinationNode() {
537 return param
.getDestinationNode();
541 public java
.util
.Map
.Entry
<Node
, NodeValue
> getSource() {
542 return new AbstractMapEntry
<Node
, NodeValue
>() {
544 public Node
getKey() {
545 return getSourceNode();
549 public NodeValue
getValue() {
550 return HashDirectedGraph
.this.get(this.getKey());
556 public Node
getSourceNode() {
557 return param
.getSourceNode();
561 public EdgeValue
getValue() {
562 return param
.getValue();
565 public EdgeValue
setValue(final EdgeValue newValue
) {
566 return param
.setValue(newValue
);
572 private final Set
<EdgeWithEdgeValue
<Node
, EdgeValue
>> edgesView
= new SetView
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, EdgeWithEdgeValue
<Node
, EdgeValue
>>(HashDirectedGraph
.this.edges(), this.getSetEdges
, this.inverseSetEdges
);
575 public Set
<EdgeWithEdgeValue
<Node
, EdgeValue
>> edges() {
576 return this.edgesView
;
580 public Set
<EdgeWithEdgeValue
<Node
, EdgeValue
>> inEdges(final Node destination
) {
581 return new SetView
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, EdgeWithEdgeValue
<Node
, EdgeValue
>>(HashDirectedGraph
.this.inEdges(destination
), this.getSetEdges
, this.inverseSetEdges
);
585 public Set
<EdgeWithEdgeValue
<Node
, EdgeValue
>> outEdges(final Node source
) {
586 return new SetView
<EdgeWithValues
<Node
, NodeValue
, EdgeValue
>, EdgeWithEdgeValue
<Node
, EdgeValue
>>(HashDirectedGraph
.this.outEdges(source
), this.getSetEdges
, this.inverseSetEdges
);
591 public Set
<Node
> adjacentFrom(final Node source
) {
592 if (this.containsKey(source
)) {
593 if (this.edges
.containsKey1(source
))
594 return this.edges
.keySetOnKey1(source
);
595 return Collections
.emptySet();
601 public Set
<Node
> adjacentTo(final Node destination
) {
602 if (this.containsKey(destination
)) {
603 if (this.edges
.containsKey2(destination
))
604 return this.edges
.keySetOnKey2(destination
);
605 return Collections
.emptySet();