【问题标题】:ConcurrentSkipListSet and re-sorting (java)ConcurrentSkipListSet 和重新排序 (java)
【发布时间】:2011-11-15 08:28:48
【问题描述】:

我正在使用 ConcurrentSkipListSet,它显然是通过多个线程访问的。现在,底层对象的 compareTo 方法使用的值随时间变化。因此,我想“更新”列表的顺序(通过使用它或类似的方法)。

但是,java.util.Collections.sort(list) 不起作用,并且仅仅重建列表可能太慢(并且会弄乱整个并发证明)。我应该看看其他解决方案吗?

它不一定会导致最佳排序(这在并发和更改值的情况下几乎是不可能的)。只要任何删除/添加调用保持线程证明(在排序时重建列表时这将是一个真正的问题),接近最优就足够了。

【问题讨论】:

  • 有趣的问题,但很难推断出任何正常的故事!什么场景,为什么是比较运算符变量?知道这一点后,可能会出现一种完全不同的方法。
  • @Will 听起来元素是可变的。
  • 一个对象在数据结构中的位置从它的位置开始排序。要改变它的位置,你必须改变结构。
  • 我会考虑重构你的集合,这样对象就不会改变。这意味着使用多个集合,因此一个集合中的元素可以相对于另一个集合中的元素“移动”。

标签: java list sorting concurrency


【解决方案1】:

每次您编辑一个项目时,它的排序顺序可能会发生变化,您必须将其从列表中删除然后更改键,然后重新插入它。


Azul Systems 的 Cliff Click 博士有一个very nice presentation,介绍了他们如何使用墓碑等进行无锁哈希表。如果您打算编写自己的跳过列表/树以将项目重新排序为单个 - 并且希望更快 - 操作,那么您也可能会走这条无锁路线。并且一定要分享你的结果:)

【讨论】:

  • +1:必须说得很清楚。您不能使用 compareTo() 或 hashCode() 和 equals() 来更改任何字段的值,并期望它能够工作。出于这个原因,最好将这些字段设为最终字段。
  • 一个更相关的问题是——当哈希集合需要这样的功能时,我们如何维护排序顺序?这就是最初的问题打算实现的目标。
  • @GauravSaxena 我们通过删除、修改密钥、然后重新插入来维护它
  • @Will :此时,您的答案与我所寻找的最接近。大概是我自己来的,所以我仍然希望有一个更令人满意的解决方案。如果没有人来,你的将被接受
  • 有趣的是,在我的游戏引擎中,甚至对于我的 hellepoll 网络服务器中的超时,我都使用了支持显式移动项目的自定义始终排序容器 - 即尝试有效地进行删除,在一个步骤中更新和插入。但是,我怀疑它是否真的值得,如果您使用 Java,您最终将不得不制作自己的容器,这可能比更快的错误多得多。我很好奇,跳过列表在实践中真的和听起来一样棒吗?表现如何?您能否将性能与经典树进行比较?
【解决方案2】:

Java API 中的这些类型的集合不支持可变元素(即 compareTo 方法发生变化的元素)。因此,唯一的方法是以原子方式重新组装一个新列表,或者按照 Will 的建议,您可以执行元素的删除、变异和重新插入。

HashSet 也有同样的问题 - 哈希桶是在插入对象时计算的,那么如果你改变对象的哈希码,你将无法做到 set.contains( ... )

确切地说,像 ConcurrentSkipListSet 和 HashSet 这样的集合在插入和删除时执行它们的比较/散列。唯一“支持”可变元素的集合不执行基于元素状态的特殊插入逻辑(例如 ArrayList)。

Set 接口状态的documentation

注意:如果将可变对象用作集合元素,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的一个元素,则不指定集合的​​行为。这种禁止的一个特殊情况是不允许集合包含自己作为元素。

以及用于 SortedSet 接口状态的 documentation

请注意,如果有序集合要正确实现 Set 接口,由有序集合维护的排序(无论是否提供显式比较器)必须与 equals 一致。 (请参阅 Comparable 接口或 Comparator 接口以了解与等于一致的精确定义。)这是因为 Set 接口是根据等于操作定义的,但排序集使用其 compareTo(或比较)方法执行所有元素比较,因此从排序集的角度来看,此方法认为相等的两个元素是相等的。一个有序集合的行为是明确定义的,即使它的排序与equals不一致;它只是不遵守 Set 接口的一般约定。

【讨论】:

  • 你有参考吗,哪里可以给出指南?
  • 您说“大多数”这些类型。你的意思是“全部”吗?如果不是:哪些类型的集合 /do/ 支持可变元素?
  • @GauravSaxena 我已经添加了一些 Java API 参考 - 这足够了吗?
  • 感谢您澄清您的回答。然而,虽然它/确实/提供了我为什么要问这个问题的正式推理,但它没有提供解决方案:(
猜你喜欢
  • 2013-03-08
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 2015-02-14
  • 2019-12-31
  • 1970-01-01
相关资源
最近更新 更多