Network.adjacentEdges returns live set
See original GitHub issueThe following test fails with a message “Live set”, when added to StandardMutableUndirectedNetworkTest
:
@org.junit.Test
public void adjacentEdges_liveSet() {
networkAsMutableNetwork.addEdge(N1, N2, E12);
java.util.Set<String> adjacentEdges = network.adjacentEdges(E12);
org.junit.Assert.assertTrue(adjacentEdges.isEmpty());
networkAsMutableNetwork.addEdge(N2, N3, E23);
org.junit.Assert.assertTrue("Live set", adjacentEdges.isEmpty());
}
Even for a mutable Network
, the method Network.adjacentEdges
should not retain a reference to the Set<String>
instance it returns. It should only return safe and unmodifiable copies.
To make things a tad more confusing, there is an existing test adjacentEdges_checkReturnedSetMutability
, in AbstractStandardUndirectedNetworkTest
, that appears to ensure the unmodifiability of this set. It is indeed unmodifiable in the sense that its add
method throws “UOE”, but it can still be changed indirectly, as shown by adjacentEdges_liveSet
. This behaviour is apparently not mentioned in the Javadoc. If we assume that it is unintended and accidential, then it should probably be fixed before somebody starts relying on it.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
@h908714124 there are a few reasons why we return live sets here, as I said in my earlier comment:
To review, these are the four options:
There’s nothing intrinsically wrong with any of these options, but here’s why we picked (2).
We chose not to provide a copy (eliminating (1) and (3)) because
u
, the returned set definitionally is the set of nodes adjacent tou
, and not a copy that may become out of date without warning.We chose to make the view immutable/unmodifiable because
You are correct that we could have chosen to return
SetView
; we didn’t because that’s not the convention either in Java’s nativeCollection
classes nor in the (many) cases where Guava collections return live views.(Incidentally, this particular weirdness is why
common.graph
’s base interfaces (Graph
,ValueGraph
,Network
) do not include mutators, as theCollections
classes do, precisely to avoid this kind of ambiguity.)Responding to this point regarding
adjacentEdges_checkReturnedSetMutability()
:That’s the primary purpose of those tests: validating that the returned set is, in fact, an unmodifiable live view. The first part of the test checks that it’s unmodifiable; the second part checks that the returned set is live, not a copy.
We do need to update the documentation for the classes responsible for constructing the implementations we provide (
{Graph, ValueGraph, Network}.Builder
); this issue will track that. Thanks for bringing this up.Documentation has now been updated in https://github.com/google/guava/pull/6051. Please reopen if you feel that this does not adequately address the concern. (We will not be changing our implementations’ behavior from using unmodifiable views, but if we can communicate this more clearly, we’re happy to update it.)