2017-04-21 27 views
0

我在試圖替換com.google.common.graph.MutableValueGraph中的元素時碰壁。在番石榴交換節點MutableValueGraph

我需要在以下數據類的更新元素的狀態(這是我知道the docs提醒要小心):

data class Frame(val method: String, val merged: Boolean = false) 

由於圖形不提供一種方法來進行相互交換節點,我滾我自己:

fun MutableValueGraph<Frame, Int>.exchangeNode(old: Frame, new: Frame): Boolean { 
    if (old == new) return true 

    if (isDirected) { 
     this.predecessors(old).forEach { 
      this.putEdgeValue(it, new, this.edgeValue(it, old)) } 
     this.successors(old).forEach { 
      this.putEdgeValue(new, it, this.edgeValue(old, it)) } 
    } else { 
     this.adjacentNodes(old).forEach { 
      this.putEdgeValue(it, new, this.edgeValue(it, old)) } 
    } 
    return this.removeNode(old) 
} 

不過,我打了一個ConcurrentModificationException的:

Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437) 
at java.util.HashMap$EntryIterator.next(HashMap.java:1471) 
at java.util.HashMap$EntryIterator.next(HashMap.java:1469) 
at com.google.common.graph.DirectedGraphConnections$1$1.computeNext(DirectedGraphConnections.java:113) 
at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145) 
at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140) 
at TestKt.exchangeNode(Test.kt:292) 
... 

聽起來很公平,因爲我在for循環中交換了一堆節點,可能試圖觸摸已交換的相鄰節點?

我的問題是:我如何替換ValueGraph中的多個節點,保持其邊緣值?

+0

目前,我做了Guava的文檔在額外的數據結構中說和追蹤可變狀態。我想,這個問題仍然有其自身的價值。 – mabi

回答

0

一種不太有效的方法,但一個肯定應避免ConcurrentModificationException是誘導從相關節點的子圖,然後在移除舊節點和添加新的,最後使用的導出子添加的邊緣值回:

fun MutableValueGraph<Frame, Int>.exchangeNode(old: Frame, new: Frame): Boolean { 
    if (old == new) return false 

    val inducedSubgraph = Graphs.inducedSubgraph(this, adjacentNodes(old) + old) 

    removeNode(old) 
    addNode(new) 

    if (isDirected) { 
     for (predecessor in inducedSubgraph.predecessors(old)) { 
      putEdgeValue(predecessor, new, inducedSubgraph.edgeValue(predecessor, old)) 
     } 
     for (successor in inducedSubgraph.successors(old)) { 
      putEdgeValue(new, successor, inducedSubgraph.edgeValue(old, successor)) 
     } 
    } else { 
     for (adjacentNode in inducedSubgraph.adjacentNodes(old)) { 
      putEdgeValue(adjacentNode, new, inducedSubgraph.edgeValue(adjacentNode, old)) 
     } 
    } 

    return true 
}