-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Description
I know that may be several other options for the semantics besides mentioned at https://github.com/google/guava/wiki/GraphsExplained#accessor-behavior, and that "generally using" one of them is not a strict guarantee of any kind, nevertheless behavior, that I've encountered today, surprised me a lot.
Accessor behavior
For accessors that return a collection, there are several options for the semantics, including:
(...)
2. Collection is an unmodifiable view (e.g.Collections.unmodifiableSet()): attempts to modify the collection in any way will throw an exception [emphasis added], and modifications to the graph will be reflected in the collection.
(...)(...); as of this writing, the built-in implementations generally use (2).
My general impression was that ImmutableGraph.nodes(), ImmutableGraph.edges() and other views should behave as if they were Collections.unmodifiableSet(). This is not always true as I will show.
@Test
public void emptyNodesAreUnmodifiable() {
ImmutableGraph<?> graph = GraphBuilder.undirected().immutable().build();
assertThrows(UnsupportedOperationException.class, () -> { graph.nodes().clear(); });
}
@Test
public void nonEmptyNodesAreUnmodifiable() {
ImmutableGraph<?> graph = GraphBuilder.undirected().immutable().addNode(1).build();
assertThrows(UnsupportedOperationException.class, () -> { graph.nodes().clear(); });
}
@Test
public void emptyEdgesAreUnmodifiable() {
ImmutableGraph<?> graph = GraphBuilder.undirected().immutable().build();
assertThrows(UnsupportedOperationException.class, () -> { graph.edges().clear(); });
}
@Test
public void nonEmptyEdgesAreUnmodifiable() {
ImmutableGraph<?> graph = GraphBuilder.undirected().immutable().putEdge(1, 2).build();
assertThrows(UnsupportedOperationException.class, () -> { graph.edges().clear(); });
}
Two of the above are failing: emptyNodesAreUnmodifiable() and emptyEdgesAreUnmodifiable().
Nothing happens when clear() is being invoked on empty view. I believe this is indeed an attempt to modify the collection, so UnsupportedOperationException should be thrown.
If you would like to make some changes, please remember about remove* and retainAll methods.
Probably related discussion on even stronger guarantees: #3480