【问题标题】:Java Set retain order?Java Set 保留顺序?
【发布时间】:2012-05-31 22:30:48
【问题描述】:

Java Set 是否保留顺序?一个方法正在向我返回一个 Set,并且据说数据是​​有序的,但在 Set 上迭代时,数据是无序的。有没有更好的方法来管理这个?是否需要更改方法以返回 Set 以外的内容?

【问题讨论】:

  • “元素的返回顺序不明确(除非该集合是某个提供保证的类的实例)。”是集合的迭代器方法所说的。找到here

标签: java sorting set


【解决方案1】:

Set 接口不提供任何排序​​保证。

它的子接口SortedSet代表了一个按照某种标准排序的集合。在 Java 6 中,有两个标准容器实现了SortedSet。他们是TreeSetConcurrentSkipListSet

除了SortedSet接口,还有LinkedHashSet类。它会记住元素插入集合的顺序,并按该顺序返回其元素。

【讨论】:

  • 此外,由于 Java 8 中的 different String hashing,Sets 和 Maps 中的默认(未排序)排序将发生变化。如果您依赖未排序的顺序,您的代码在 Java 8 下的行为会有所不同。
  • 我知道类不排序是正常的,但我期望的行为是在它们被引入时留下它们而不是弄乱顺序,而是每次一个元素时都洗牌聚合。您的解决方案不是最佳的,因为那样我将不得不实现一个完整的结构,以便按照它们被引入的相同方式对它们进行排序:S
  • @White_King:集合是一个数学概念,不包含“插入顺序”的概念,因此 Java 接口遵循其约定是有意义的。有有序集合,但顺序由关系(Java 中的比较器)指定,再次将集合论中的定义与 Java 中的定义相匹配。您对它保持插入顺序的期望可能来自列表,但集合不是列表。
【解决方案2】:

LinkedHashSet 是您所需要的。

【讨论】:

  • List 不是Set(它不保证成员资格的唯一性)。
  • 在许多业务独特的情况下,不能仅使用 List 而不是 Set 来保留订单。 LinkedHashSet 维护顺序和存储唯一性。
【解决方案3】:

正如许多成员所建议的那样,使用 LinkedHashSet 来保持集合的顺序。 你可以使用这个实现来包装你的集合。

SortedSet 实现可用于排序顺序,但为了您的目的,请使用 LinkedHashSet

同样来自文档,

“此实现将其客户端从 HashSet 提供的未指定的、通常混乱的排序中解脱出来,而不会增加与 TreeSet 相关的成本。它可用于生成与原始集合具有相同顺序的集合的副本,无论原始集合的实现:"

来源:http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

【讨论】:

    【解决方案4】:

    Set 只是一个接口。为了保持顺序,您必须使用该接口和子接口 SortedSet 的特定实现,例如 TreeSet 或 LinkedHashSet。你可以用这种方式包装你的 Set:

    Set myOrderedSet = new LinkedHashSet(mySet);
    

    【讨论】:

      【解决方案5】:

      要保留订单,请使用ListLinkedHashSet

      【讨论】:

      • 这是LinkedHashSet,而不是...Map
      • 我需要一个集合而不是一个列表,我需要一个集合,它还保留了我猜的对象的注入顺序
      【解决方案6】:

      以下是 Java 中可用的标准 Set 实现的顺序特征的快速总结:

      1. 保持插入顺序:LinkedHashSetCopyOnWriteArraySet(线程安全)
      2. 保持集合内的项目排序:TreeSetEnumSet(特定于枚举)和ConcurrentSkipListSet(线程安全)
      3. 不按任何特定顺序保留项目:HashSet(您尝试过的那个)

      对于您的具体情况,您可以先对项目进行排序,然后使用 1 或 2 中的任何一个(很可能是 LinkedHashSetTreeSet)。或者,更有效地,您可以将未排序的数据添加到 TreeSet,它会自动为您处理排序。

      【讨论】:

        【解决方案7】:

        LinkedHashSet 是 HashSet 的有序版本,它维护一个跨所有元素的双向链表。当您关心迭代顺序时,请使用此类而不是 HashSet。

        【讨论】:

          【解决方案8】:

          来自Set.iterator()的javadoc:

          返回此集合中元素的迭代器。返回的元素没有特定的顺序(除非这个集合是某个提供保证的类的实例)。

          而且,正如shuuchan 所述,TreeSet 是具有保证顺序的Set 的实现:

          元素使用它们的自然顺序或在集合创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。

          【讨论】:

            【解决方案9】:

            一般set是不保持顺序的,比如HashSet是为了快速找到一个元素,但是你可以试试LinkedHashSet它会保持你输入的顺序。

            【讨论】:

              【解决方案10】:

              有两种不同的东西。

              1. 对集合中的元素进行排序。我们有 SortedSet 和类似的实现。
              2. 维护集合中的插入顺序。可以使用 LinkedHashSet 和 CopyOnWriteArraySet(线程安全)。

              【讨论】:

                【解决方案11】:

                Set 接口本身并没有规定任何特定的顺序。但是,SortedSet 确实如此。

                【讨论】:

                  【解决方案12】:

                  Set 返回的迭代器不应该以有序的方式返回数据。 看到这个Two java.util.Iterators to the same collection: do they have to return elements in the same order?

                  【讨论】:

                    【解决方案13】:

                    只有SortedSet可以对Set进行排序

                    【讨论】:

                    • 问题是关于保留插入顺序(恰好是排序的)。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-03-12
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-08-08
                    相关资源
                    最近更新 更多