【问题标题】:Order of elements in a set in javajava中集合中元素的顺序
【发布时间】:2017-06-16 18:07:13
【问题描述】:

如果我从同一个集合中创建 2 个列表,我可以确定我在两个列表中得到相同的排序吗? (我不关心顺序,只要两个列表具有相同的顺序,并且我不在创建两个列表之间的集合上执行任何操作。)

List l = new ArrayList(set);

List l1 = new ArrayList(set);

我了解创建这些列表并获得相同顺序的方法是有保证的,并且我没有充分的理由以这种方式创建两个列表,但我想知道为什么在一个如果不对其执行修改操作,set 将会改变。

编辑:该集合是一个无序的 HashSet

【问题讨论】:

  • 如果它是一个哈希集,如果它在中间发生突变,则否(不能保证排序,但如果不修改集合就不会改变)。如果是其他任何东西,则将定义排序,以便您可以根据它进行调整。
  • 这完全取决于实现。我可以设想一个实现,其中迭代集合会以某种方式改变集合的顺序。非常不可能,但有可能,并且不能保证它不会发生。
  • 没有。 Set 对其迭代顺序不提供任何保证。甚至不是一致的。它可能会选择以您的访问权限为借口来整理内部结构,从而改变下一次迭代的顺序。
  • @Boris,这不是Set 本身的属性。例如TreeSetLinkedHashSet等一些集合保证了迭代顺序。
  • @aetheria 绝对是:来自JavaDoc for Set - “元素以无特定顺序返回”。 IE。 Set 特别声明它不提供任何保证。谈论具体的植入完全无关紧要——就像说Set 可以存储在数据库中,因为PersistentSet 恰好是。

标签: java set


【解决方案1】:

您将适当地在列表ll1 中获得相同的排序。但由于大多数 Set 是无序的,因此您无法保证会有相同的顺序。

从技术上讲,您可以编写Set 接口的实现,该接口在每次调用任何方法时都会更改其顺序。这仍然可以实现接口。

由于在构造函数new ArrayList(Collection)中调用了集合的toArray方法,我们可以看看Set#toArray()Javadoc

返回一个包含此集合中所有元素的数组。如果此集合对其迭代器返回其元素的顺序做出任何保证,则此方法必须以相同的顺序返回元素。

虽然Set#iterator() 的 Javadoc 说没有一般保证:

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

鉴于此,我强烈建议您不要依赖列表的顺序。

【讨论】:

    【解决方案2】:

    根据documentation

    public ArrayList(Collection c) 构造一个列表 包含指定集合的​​元素,按它们的顺序排列 由集合的迭代器返回

    所以这真的取决于Set接口实现类,如果顺序是恒定的。

    例如,如果您使用LinkedHashSet,则迭代顺序是可预测的。

    【讨论】:

    • 我很确定目前主要的实现没有提供任何不正确的集合实现,但这并不意味着不可能有。
    • 就我而言,我使用的是无序哈希集。
    • 对于 HashSet public Iterator<E> iterator() 返回此集合中元素的迭代器。返回的元素没有特定的顺序。看来你不能依赖这个命令。
    【解决方案3】:

    有些结构的订单是否得到保证。如果我们提到Java实现的Set接口,则无法保证。 ArrayList 的构造函数很可能使用了Set 的迭代器。所以这两个列表肯定总是包含相同的元素但顺序。这就是为什么Set 使用contains 关键字而不是find 来检查元素是否存在的原因。

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

    除了SortedSet接口,还有 LinkedHashSet 班级。它记住的顺序 元素被插入到集合中,并返回其中的元素 顺序。

    【讨论】:

      【解决方案4】:

      一种对无序集合(如Set)施加所需(自然或其他)顺序的方法是从给定集合创建有序Set(换句话说,SortedSet)。如果您的集合不是太大并且您只关心可预测的迭代顺序,您可以这样做:

      // set = ...
      List<? extends Comparable> list = new TreeSet<>(set).stream().collect(Collectors.toList());
      

      这假定集合由可比较的元素组成。或者,您可以在 TreeSet 构造函数中使用自己的比较器。但是,如果元素本身不可比较,则创建此类比较器可能会出现一些问题。

      【讨论】:

        【解决方案5】:

        这里有一些互测很好的答案,我可以提出一个解决方案。

        List list = new ArrayList(set);
        
        List secondList = new ArrayList(list);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多