我正试图替换com.google.common.graph.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 :(得分: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
}