Remove / add objects and avoid ConcurrentModificationException
in
Programming Questions
•
7 months ago
I have a node layout which make together a map.
On that map i use pathfinding to find routes.
The format i used to load was not perfect so every node is on top of another node, for example in the image B, C and D will be on the same position.
My goal is to keep only one of those 3 and relink the links.
This is what the Node class looks like.
- class Node implements Comparable<Node> {
- int id;
- float lon;
- float lat;
- // A*
- float f = 0;
- float g = 0;
- float h = 0;
- Node parent;
- HashSet<Node> links = new HashSet<Node>();
- Node() {
- }
- Node(float lon, float lat) {
- this.id = idCount++;
- this.lon = lon;
- this.lat = lat;
- }
- Node(int id, float lon, float lat) {
- this.id = id;
- this.lon = lon;
- this.lat = lat;
- }
- void linkToNode(Node n) {
- links.add(n);
- }
- void reset() {
- f = g = h = 0;
- parent = null;
- }
- int compareTo(Node n) {
- if(f < n.f) return -1;
- if(f == n.f) return 0;
- return 1;
- }
- }
So to reform what i want:
I want B and C removed and A and E connected to D (or anything like that).
I either have a bug, or i get a ConcurrentModificationException or a IllegalStateException.
Here i have 3 attempts (i have more attempts but those where the best / closest i guess).
There is one ArrayList called nodes which hold all nodes. So the overlapping ones have to be removed from there, except one. And then every node has a hashSet called links, the ones that get removed from nodes shouldn't be present anymore in links.
I hope this is enough to help.
If not i will upload the files required to run my code later.
- void mergeOverlappingNodes() {
- for(int i = nodes.size()-1; i >= 0; i--) {
- Node n = nodes.get(i);
- for(Node linkedNode : n.links) {
- if ( (n.lon == linkedNode.lon) && (n.lat == linkedNode.lat)) {
- nodes.remove(linkedNode);
- i--;
- for(Node linkedNodeFromTheOneToRemove : linkedNode.links) {
- linkedNodeFromTheOneToRemove.links.remove(linkedNode);
- linkedNodeFromTheOneToRemove.links.add(n);
- }
- }
- }
- }
- }
- void mergeOverlappingNodes() {
- Iterator<Node> itr = nodes.iterator();
- while(itr.hasNext()) {
- Node n = itr.next();
- boolean remove = false;
- // check if the node can be removed
- for(Node linkedNode : n.links) {
- if ( (n.lon == linkedNode.lon) && (n.lat == linkedNode.lat)) {
- remove = true;
- break;
- }
- }
- for(Node linkedNode : n.links) { //ConcurrentModificationException
- linkedNode.links.remove(n);
- }
- for(Node linkedNode1 : n.links) {
- for(Node linkedNode2 : n.links) {
- linkedNode1.links.add(linkedNode2);
- }
- }
- /*
- for(Node aLinkedNodeFromTheOneToRemove : linkedNode.links) {
- //if(aLinkedNodeFromTheOneToRemove == n) println("true");
- aLinkedNodeFromTheOneToRemove.links.remove(linkedNode);
- aLinkedNodeFromTheOneToRemove.links.add(n);
- }
- */
- //linkedNode.links.add(n);
- if(remove) itr.remove();
- }
- }
One of the firsts, which has no error but a bug..
- void mergeOverlappingNodesOld() {
- Node theNode, otherNode;
- for (int i = nodes.size()-1; i >= 0; i--) {
- theNode = nodes.get(i);
- ArrayList<Node> nodesOnTheSamePosition = new ArrayList<Node>();
- // in this loop we find all nodes on the same position
- // and add them to the ArrayList: nodesOnSamePosition
- for (int j = nodes.size()-1; j >= 0; j--) {
- otherNode = nodes.get(j);
- if (theNode == otherNode) continue;
- if ( (theNode.lon == otherNode.lon) && (theNode.lat == otherNode.lat)) {
- nodesOnTheSamePosition.add(otherNode);
- }
- }
- // now relink and remove
- for(Node aNodeOnTheSamePosition : nodesOnTheSamePosition) {
- for(Node linkedNode : aNodeOnTheSamePosition.links) {
- theNode.links.add(linkedNode);
- }
- nodes.remove(aNodeOnTheSamePosition);
- theNode.links.remove(aNodeOnTheSamePosition);
- }
- // added in attempt to bug fix
- // now added above which in theory should work
- /*
- for(Node aNodeOnTheSamePosition : nodesOnTheSamePosition) {
- theNode.links.remove(aNodeOnTheSamePosition);
- }
- */
- // since nodes.size() is changed now we have to decrement i
- i -= nodesOnTheSamePosition.size();
- }
- /*
- Node node1, node2;
- HashSet<Node> nodesToRemove = new HashSet<Node>();
- //HashSet<Node> nodesNotToRemove = new HashSet<Node>();
- for (int i = nodes.size()-1; i >= 0; i--) {
- node1 = nodes.get(i);
- for (int j = nodes.size()-1; j >= 0; j--) {
- node2 = nodes.get(j);
- if (node1 == node2) continue;
- if (nodesToRemove.contains(node1)) continue;
- if ( (node1.lon == node2.lon) && (node1.lat == node2.lat)) {
- HashSet<Node> links = new HashSet<Node>(node1.links);
- for (Node n : links) {
- n.links.remove(node1);
- n.links.add(node2);
- // we have to remove them later else things go wrong
- nodesToRemove.add(node1);
- //nodesNotToRemove.add(node2);
- }
- }
- }
- }
- // println(nodesToRemove.size());
- Iterator<Node> itr = nodesToRemove.iterator();
- while (itr.hasNext ()) {
- Node nodeToRemove = itr.next();
- //if(nodesNotToRemove.contains(nodeToRemove)) continue;
- nodes.remove(nodeToRemove);
- }
- */
- // check if correct
- /*
- for (Node n1 : nodes) {
- for (Node n2 : nodes) {
- if (n1 == n2) continue;
- if ( (n1.lon == n2.lon) && (n1.lat == n2.lat)) {
- println("my code is wrong...");
- }
- }
- }
- */
- }
1