Refer to types by interface instead of implementation
Instead of this:
HashMap<Vertex, HashSet<Vertex>> adj = new HashMap<Vertex, HashSet<Vertex>>();
This is preferable:
Map<Vertex, Set<Vertex>> adj = new HashMap<Vertex, Set<Vertex>>();
Pointless code
The parameterless constructor with empty body is pointless, you can safely remove it.
Make fields final when possible
The member variable adj
is never reassigned, therefore it can be final
.
Validate first before other operations
In addDirectedToVertex
, you first add target to the graph if it's not there yet, and then check if source
is valid or not, otherwise throw exception. It would be letter to change the order of operations, do the validation first.
A javadoc string about the unchecked exception would be nice too.
Simplify hasEdge
The if-else can be simplified with a ternary:
return targets != null && targets.contains(target)
Inconsistent handling of invalid parameters
In outEdges
, if the specified source doesn't exist, you return an empty list. But such source is effectively invalid, and many of your other methods throw an exception in such situations. It would be good to be consistent and so likewise here.
It's also not great to give a variable the same name as that of a method.
Using a POD class vs printing
Using a POD class is clearly the lesser evil. Don't use printing to verify "with your eyes".