如果我从同一组数据中创建两个列表,我可以确定这两个列表具有相同的顺序吗?(只要这两个列表具有相同的顺序且我在创建两个列表之间没有对该组数据进行任何操作即可,我不关心顺序)
List l = new ArrayList(set);
List l1 = new ArrayList(set);
我理解到有保证的方法可以创建这些列表并确保其顺序不变,因此没有必要用这种方式创建两个列表。但我想知道,如果在集合中没有执行修改操作,为什么元素的排序会改变。
编辑:该集合是无序HashSet。
l
和l1
中获得相同的顺序。但由于大多数集合是无序的,您不能保证它们的顺序相同。Set
接口的代码,每次调用任何方法时都会更改其顺序。这仍将满足接口。new ArrayList(Collection)
中调用了集合的toArray
方法,因此我们可以查看Set#toArray()
的Javadoc:
而返回包含此集合中所有元素的数组。如果此集合对其迭代器返回其元素的顺序作出任何保证,则此方法必须按相同顺序返回元素。
Set#iterator()
的Javadoc说没有一般性的保证:
返回此集合中的元素的迭代器。元素以无特定顺序返回(除非该集合是某个提供保证的类的实例)。
鉴于此,我强烈建议您不要依赖列表的顺序。
根据文档,
public ArrayList(Collection c) 构造包含指定集合元素的列表,并按照集合迭代器返回的顺序排序
因此,迭代顺序是否始终相同实际上取决于Set
接口的实现类。
例如,如果使用LinkedHashSet
,则迭代顺序是可预测的。
public Iterator<E> iterator()
返回一个迭代器,用于遍历集合中的元素。这些元素没有特定的顺序返回。看起来您不能依赖于这个顺序。 - MaxZoom// set = ...
List<? extends Comparable> list = new TreeSet<>(set).stream().collect(Collectors.toList());
这假设集合中的元素是可比较的。或者,您可以在TreeSet
构造函数中使用自己的比较器。然而,如果元素本身不可比较,则创建此类比较器可能会存在一些问题。
有些结构是保证顺序的,而有些则不是。如果我们提到Java实现的Set
接口,那么就没有保证了。很可能ArrayList
的构造函数使用了Set
的迭代器。因此,两个列表肯定包含相同的元素,但顺序不同。这实际上就是为什么Set
使用contains
关键字而不是find
来检查元素是否存在。
SortedSet
,代表按某些标准排序的集合。在Java 6中,有两个标准容器实现了SortedSet
。它们是TreeSet
和ConcurrentSkipListSet
。
除了SortedSet
接口外,还有LinkedHashSet
类。它记住元素插入集合的顺序,并以该顺序返回其元素。这里有一些有趣且不错的答案,我可以提供一个解决方案。
List list = new ArrayList(set);
List secondList = new ArrayList(list);
Set
可能会利用访问来整理内部结构,从而在下一次迭代时更改顺序。 - Boris the SpiderSet
本身的属性。例如,一些集合(如TreeSet
和LinkedHashSet
)保证迭代顺序。 - ᴇʟᴇvᴀтᴇSet
- "元素没有特定的顺序返回". 也就是说,Set
明确声明它不提供任何保证。谈论具体的实现是完全无关紧要的 - 就像说Set
可以被存储在数据库中一样,因为恰好有PersistentSet
。 - Boris the SpiderSet
,就不应该依赖于迭代顺序。我的意思是(严谨地说),一些Set
的实现确实保证了迭代顺序。它们仍然是Set
,也就是说,确实有保证迭代顺序的Set
。Set
的区别特性在于它不包含重复项。所有的实现都必须遵守这个约束条件。但是实现可以自由地提供关于迭代顺序或持久性的保证。 - ᴇʟᴇvᴀтᴇ