question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Network.adjacentEdges returns live set

See original GitHub issue

The 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:closed
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jrtomcommented, Jan 19, 2022

@h908714124 there are a few reasons why we return live sets here, as I said in my earlier comment:

  • it entails less overhead (than making a copy)
  • in our judgement providing a view that changes as the graph changes is overall more useful, and less surprising, than a copy that does not
  • it is consistent with design decisions elsewhere in Guava

To review, these are the four options:

  1. immutable copy
  2. immutable view
  3. mutable copy
  4. mutable view

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

  • it’s slower
  • we felt that it was less surprising that if you ask for the set of nodes adjacent to u, the returned set definitionally is the set of nodes adjacent to u, and not a copy that may become out of date without warning.
  • it preserves the most options for the user: the user can make a copy of a live view, but they can’t get a live view given a copy.

We chose to make the view immutable/unmodifiable because

  • we wanted to have only one mechanism for modifying the graph
  • graphs are, by design, not mutable by default, and so returning a modifiable view from an accessor would have created confusion
  • trying to keep the internal data structures consistent in the face of multiple mutation entry points would have added complexity to our implementations

You are correct that we could have chosen to return SetView; we didn’t because that’s not the convention either in Java’s native Collection 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 the Collections classes do, precisely to avoid this kind of ambiguity.)

Responding to this point regarding adjacentEdges_checkReturnedSetMutability():

Because adjacentEdges is a live set view, the current assertion is always trivially true, regardless of any prior modifications to the network. We’re literally asserting that adjacentEdges is equal to itself.

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.

0reactions
jrtomcommented, May 19, 2022

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.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

com.google.common.graph.Network.adjacentEdges java code ...
Returns all edges in this network, in the order specified by #edgeOrder(). incidentNodes. Returns the nodes which are the endpoints of edge in...
Read more >
Network (Guava: Google Core Libraries for Java 22.0-android API)
Set <E>, inEdges(N node). Returns all edges in this network which can be traversed in the direction (if any) of the edge to...
Read more >
Network (Guava: Google Core Libraries for Java 20.0 API) - javadoc.io
Method Summary ; Set<E>, inEdges(Object node). Returns all edges in this network which can be traversed in the direction (if any) of the...
Read more >
AbstractNetwork (Guava: Google Core Libraries for Java 27.0.1 ...
Returns a live view of this network as a Graph . int, degree(N node). Returns the count of node 's ...
Read more >
igraph.pdf - The Comprehensive R Archive Network
to specify a vector or set of vertices, in all igraph functions. ... Create adjacency lists from a graph, either for adjacent edges...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found