0

I am writing an algorithm to set up an undirected graph of objects. After adding and removing edges correctly to specific elements in the graph, I reach a certain point where I get this error.

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableCollection.add(Unknown Source)
    at UndirectedGraph.addEdge(UndirectedGraph.java:81)

Note that this is after the program had already allowed me to add edges to the graph and nothing has changed in the way I input objects into the addEdge method. The code for addEdge is:

private final Map<Object, Set<Object>> mGraph = new HashMap<Object, Set<Object>>();

public void addEdge(Object one, Object two) {
    /* Confirm both endpoints exist. */
    if (!mGraph.containsKey(one) || !mGraph.containsKey(two))
        throw new NoSuchElementException("Both nodes must be in the graph.");

    /* Add the edge in both directions. */
    mGraph.get(one).add(two);
    mGraph.get(two).add(one);
}

While running the debugger, I found that at the beginning of the code when mGraph.get(one) is called it returns a HashSet, but when the error occurs it returns Collections$UnmodifiableSet. Why is this happening?

matrix66
  • 3
  • 1
  • 2

1 Answers1

2

You don't say here how mGraph is populated. If any of the entries are unmodifiable sets--especially if those are views of some other data structures--then it could cause that error message. To the chagrin of a lot of developers, many operations on the Java collections classes are optional, and may not be supported even for implementors. Collections.unmodifiableCollection returns read-only views, and that method is often used for views of other collections (such as Map.keySet).

To ensure that only HashSet instances are put into mGraph, explicitly create a new HashSet<Object> and addAll from the source set, or use the new HashSet<Object>(existingSet) constructor.

Jeff Bowman
  • 74,544
  • 12
  • 183
  • 213
  • mGraph is populated with a method called addNode. It uses mGraph.put(node, new HashSet) when populating the graph. I am wondering why get(node) method returns different things when I'm using the same method of adding edges to the graph. – matrix66 Jul 07 '15 at 21:42
  • Me too! There's nothing you've posted that would indicate that that should happen. – Jeff Bowman Jul 07 '15 at 21:43
  • one and two in the method are found using an ArrayList of Objects that I pulled from the graph originally when no edges were connected. I call the get(index) method on the ArrayLists to pull the specific objects I want to add edges to. Is this the correct way to go about it? – matrix66 Jul 07 '15 at 21:55
  • 1
    @matrix66 Update your question with code that shows me what you use for `mGraph.put(...)` please! – YoYo Jul 07 '15 at 21:58
  • I found the problem. I was calling a method called edgesFrom(node) that returned an immutable set and storing it back into mGraph in other methods. This caused them to be stored as immutable sets instead of hashsets. Thank you for your help. – matrix66 Jul 07 '15 at 22:03