java中集合中元素的顺序

问题描述 投票:0回答:6

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

List l = new ArrayList(set);

List l1 = new ArrayList(set);

我知道有保证的方法可以创建这些列表并获得相同的顺序,并且我没有充分的理由以这种方式创建两个列表,但我想知道为什么集合中元素的顺序会如果没有对其进行任何修改操作,则会发生变化。

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

java set
6个回答
9
投票

您将可能在列表

l
l1
中获得相同的顺序。但由于大多数 Set 都是无序的,因此您无法保证会有相同的顺序。

从技术上讲,您可以编写

Set
接口的实现,每次调用任何方法时都会更改其顺序。这仍然可以实现接口。

由于在构造函数

new ArrayList(Collection)
中调用了集合的
toArray
方法,我们可以看一下Set#toArray()
Javadoc

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

虽然

Set#iterator()
的 Javadoc 表示没有一般保证:

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

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


4
投票

根据文档

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

因此,如果顺序不变,这实际上取决于

Set
接口实现类。

例如,如果您使用

LinkedHashSet
,迭代顺序是可预测的。


0
投票

他们的订单有保证或不保证的结构。如果我们提到 Java 实现的

Set
接口,则没有任何保证。
ArrayList
的构造函数很可能利用
Set
的迭代器。因此,两个列表肯定包含始终相同的元素,但顺序相同。这实际上就是为什么
Set
使用
contains
关键字而不是
find
来检查元素是否存在。

它的子接口,

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

除了

SortedSet
界面之外,还有
LinkedHashSet
课。它会记住的顺序 元素被插入到集合中,并返回其中的元素 订购。


0
投票

对无序集合(如

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

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

这假设该集合由可比较的元素组成。或者,您可以在

TreeSet
构造函数中使用自己的比较器。然而,如果元素本身不具有可比性,那么创建这样的比较器可能会出现一些问题。


0
投票

SequencedSet

Java 21 带来了顺序集合。新界面包括

SequencedSet

SequencedSet
NavigableSet
SortedSet
现有接口的超接口。

这是一组具有自然排序(按字母顺序)的

String
对象。

List < String > namesList = List.of( "Bob" , "Carol" , "Alice" , "Alice" );
SequencedSet < String > namesInAlphabeticalOrder = new TreeSet <>( namesList );

姓名按字母顺序 = [爱丽丝、鲍勃、卡罗尔]

我们在这里看到两种行为:

  • 根据任何
    Set
    的定义,消除了重复项。 (一个“爱丽丝”而不是两个。)
  • SequencedSet
    中灌输和维持自然秩序,如
    TreeSet

-3
投票

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

List list = new ArrayList(set);

List secondList = new ArrayList(list);
© www.soinside.com 2019 - 2024. All rights reserved.