Scala :: PriorityQueue => 更新特定项目的优先级

Posted

技术标签:

【中文标题】Scala :: PriorityQueue => 更新特定项目的优先级【英文标题】:Scala :: PriorityQueue => update priority of specific item 【发布时间】:2012-08-28 10:09:39 【问题描述】:

我已经实现了从头部提取项目的例程,更新它的优先级并使用这样的非阻塞方法将其放回队列(使用 AtomicReference)

def head(): Entry = 
  def takeAndUpdate(e: Entry, success: Boolean): Entry = 
    if (success) 
      return e
    
    val oldQueue = queueReference.get()
    val newQueue = oldQueue.clone()
    val item = newQueue.dequeue().increase()
    newQueue += item
    takeAndUpdate(item.e, queueReference.compareAndSet(oldQueue, newQueue))
  
  takeAndUpdate(null, false)

现在我需要找出队列中的任意条目,更改它的优先级并将其放回队列。 PriorityQueue 似乎不支持这一点,那么我应该使用哪个类来完成所需的行为?

与Change priority of items in a priority queue有关

【问题讨论】:

您是否尝试过使用不同的方法:例如SortedSet(或SortedMap)? @oxbow_lakes 现在我正在尝试用 TreeSet 实现它 你没有定义上面的load是什么。 【参考方案1】:

使用不可变的树形图 (immutable.TreeMap) 来完成此操作。您必须以某种方式找到所需的条目 - 最好的方法是将用于查找条目的部分信息 (Key) 与键关联,以及您希望返回的实际条目与值在地图中(称之为Entry)。

queueReference 重命名为treeReference。在您创建集合的代码部分,使用immutable.TreeMap[Key, Entry](<list of elements>)

然后像这样修改代码:

def updateKey(k: Key) 
  @annotation.tailrec def update(): (Key, Entry) = 
    val oldTree = treeReference.get()
    val entry = oldTree(k)
    val newPair = modifyHoweverYouWish(k, entry)
    val newTree = (oldTree - k) + newPair
    if (treeReference.compareAndSet(oldTree, newTree)) newPair
    else update()
  
  update()

如果compareAndSet 失败,您必须像在源代码中所做的那样重复。最好使用@tailrec,如上图,保证函数是尾递归的,防止潜在的堆栈溢出。

或者,您可以使用immutable.TreeSet - 如果您知道对您的Entry 对象的确切引用,您可以使用它通过上面的- 删除元素,然后在调用increase() 后将其添加回来.代码几乎一样。

【讨论】:

以上是关于Scala :: PriorityQueue => 更新特定项目的优先级的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 PriorityQueue (Scala) 的隐式排序时遇到问题

Scala PriorityQueue 冲突解决?

scala.collection.mutable.PriorityQueue:与案例类的 2 个或更多属性进行比较

Scala 问题对 Stack[A] 使用 PriorityQueue 非默认排序

创建一个包含三元组的 PriorityQueue,并返回 Scala 中的最小第三个元素?

按非案例类的字段排序 PriorityQueue