一个有序的集合,用户可以精确控制每个元素在列表中的插入位置。用户可以通过元素的整数索引(列表中的位置)访问元素,并在列表中搜索元素。

Set 不同,列表通常允许重复元素。列表通常允许成对的元素 e1e2 满足 e1.equals(e2),并且如果允许 null 元素,通常也允许多个 null 元素。不排除有人希望实现一个禁止重复元素的列表,在用户尝试插入重复元素时抛出运行时异常,但可能这种用法比较少见。

List 接口对 iteratoraddremoveequalshashCode 方法添加了比 Collection 接口更多的规定。

List 接口提供了四种方法来按位置(索引)访问列表元素。列表(如同 Java 数组)是从零开始的。请注意,对于某些实现(例如 LinkedList 类),这些操作的执行时间可能与索引值成正比。因此,如果调用者不了解具体实现,通常遍历列表中的元素要比通过索引访问更优。

List 接口提供了一种特殊的迭代器,称为 ListIterator,除了 Iterator 接口提供的常规操作外,还允许元素的插入和替换,以及双向访问。提供了一种方法来获取从列表中指定位置开始的列表迭代器。

List 接口提供了两种方法来搜索指定对象。从性能角度来看,这些方法应谨慎使用。在许多实现中,它们会执行代价高昂的线性搜索。

List 接口提供了两种方法来高效地在列表中的任意位置插入和移除多个元素。

注意:虽然允许列表将自己包含为元素,但应极为谨慎:在这种列表上,equalshashCode 方法不再有明确的定义。

注意:虽然列表中包含自身作为元素是被允许的,但应极为谨慎:在这样的列表上,equals(相等性判断)和 hashCode(哈希码计算)方法不再有良好的定义。

一些列表实现对其可以包含的元素有一定的限制。例如,某些实现禁止空元素,某些则对其元素类型有规定。尝试添加不符合要求的元素会抛出未经检查的异常,通常是 NullPointerExceptionClassCastException。尝试查询不符合要求元素的存在性可能会抛出异常,也可能只是返回 false;一些实现会表现为前者行为,而另一些则表现为后者。更一般地说,尝试对不符合要求的元素进行操作,如果该操作不会导致将不符合要求的元素插入列表中,可能会抛出异常,也可能成功,这取决于具体的实现。这类异常在此接口的规范中标记为“可选”。

一、类层次关系

二、源码

1
2
public interface List<E> extends SequencedCollection<E> {
}

1、来自 Collection 的方法

继承自 Collection 接口的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int size();

boolean isEmpty();

boolean contains(Object o);

Object[] toArray();

<T> T[] toArray(T[] a);

boolean add(E e);

boolean remove(Object o);

boolean containsAll(Collection<?> c);

boolean addAll(Collection<? extends E> c);

boolean removeAll(Collection<?> c);

boolean retainAll(Collection<?> c);

void clear();

2、来自 Iterable 的方法

继承自 Iterable 接口的方法

1
Iterator<E> iterator();

3、List 接口中定义的方法

List 接口中声明的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
boolean addAll(int index, Collection<? extends E> c);

// Positional Access Operations

E get(int index);

E set(int index, E element);

void add(int index, E element);

E remove(int index);

// Search Operations

int indexOf(Object o);

int lastIndexOf(Object o);

// List Iterators

ListIterator<E> listIterator();

ListIterator<E> listIterator(int index);

// View

List<E> subList(int fromIndex, int toIndex);

3.1 addAll 方法

List 接口中 addAll 方法有两个重载,除了继承自 Collection 接口的方法外,还有另外的 boolean addAll(int index, Collection<? extends E> c); 方法。

该方法将指定集合中的所有元素插入到此列表中指定位置(可选操作)。将当前位于该位置的元素(如果有)以及后续元素向右移动(增加它们的索引)。

新元素将按照入参集合的迭代器返回的顺序出现在此列表中。如果在该方法执行过程中修改了入参集合,则该方法将会发生不可预料的行为。比如,入参中的集合传入的是当前集合且非空时,就会发生这种情况。

3.2 get 方法

该方法返回入参中指定索引位置处的元素。

3.2 set 方法

该方法将列表中指定位置的元素替换为指定元素。

3.3 add 方法

除了继承自 Collection 接口的 boolean add(E e); 方法外,List 接口中定义了重载的 void add(int index, E element); 方法。

该方法会在此列表中的指定位置插入指定元素(可选操作)。将当前位于该位置的元素(如果有的话)和后续元素向右移动(将其索引加一)。

3.4 remove 方法

除了继承自 Collection 接口的 boolean remove(Object o); 方法外,List 接口还定义了重载的 E remove(int index); 方法。

该方法会删除此列表中指定位置的元素(可选操作)。将任何后续元素向左移动(从其索引中减去一)。并返回从列表中删除的元素。

3.5 搜索对象方法 indexOf

int indexOf(Object o);

返回指定元素在这个列表中第一次出现的索引,如果这个列表不包含该元素,则返回 -1。

返回满足 Objects.equals(o, get(i)) 的最低索引 i,如果没有这样的索引则返回 -1。

3.6 搜索对象方法 lastIndexOf

int lastIndexOf(Object o);

返回指定元素在这个列表中最后一次出现的索引,如果这个列表不包含该元素,则返回 -1。

返回满足 Objects.equals(o, get(i)) 的最高索引 i,如果没有这样的索引则返回 -1。

3.7 ListIterator 迭代器

关于该迭代器,List 接口中有两个方法:

  • ListIterator<E> listIterator();,该方法返回此列表中元素的列表迭代器(按照正常顺序)。
  • ListIterator<E> listIterator(int index);,此方法返回此列表中元素的列表迭代器(按正确顺序),从列表中的指定位置开始。指定的索引表示初始调用 next 时将返回的第一个元素。初始调用 previous 将返回指定索引减一的元素。

关于 ListIterator 的内容,请查看:迭代器 ListIterator | z2huo

3.8 视图列表 subList

List 接口中定义了 List<E> subList(int fromIndex, int toIndex); 方法用来返回列表的子列表视图。

该方法会返回此列表中从指定的 fromIndex(包含)到 toIndex(不包含)之间部分的视图。如果 fromIndextoIndex 相等,则返回的列表为空。

返回的列表以此列表为基础,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。

此方法消除了对显式范围操作的需要(这类操作通常存在于数组中)。对列表的操作都可以通过传递子列表视图而不是整个列表来进行范围操作。例如,以下用法可以从列表中删除一部分元素:

1
list.subList(from, to).clear();

类似的用法可以用于 indexOflastIndexOfCollections 类中的所有算法也可以应用于子列表。

如果通过返回的列表以外的方式对基础列表(即此列表)进行了结构性修改,则此方法返回的列表可能会出问题。结构性修改是指那些改变此列表大小的修改,或者以其他方式扰乱列表,使正在进行的迭代可能产生不正确的结果。

4、来自 SequencedCollection 的方法

从 Java 21 开始,继承自 SequencedCollection 接口的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// ========== SequencedCollection ==========

/**
* @since 21
*/
default void addFirst(E e) {
this.add(0, e);
}

/**
* @since 21
*/
default void addLast(E e) {
this.add(e);
}

/**
* @since 21
*/
default E getFirst() {
if (this.isEmpty()) {
throw new NoSuchElementException();
} else {
return this.get(0);
}
}

/**
* @since 21
*/
default E getLast() {
if (this.isEmpty()) {
throw new NoSuchElementException();
} else {
return this.get(this.size() - 1);
}
}

/**
* @since 21
*/
default E removeFirst() {
if (this.isEmpty()) {
throw new NoSuchElementException();
} else {
return this.remove(0);
}
}

/**
* @since 21
*/
default E removeLast() {
if (this.isEmpty()) {
throw new NoSuchElementException();
} else {
return this.remove(this.size() - 1);
}
}

/**
* @since 21
*/
default List<E> reversed() {
return ReverseOrderListView.of(this, true); // we must assume it's modifiable
}

5、不可修改 List

从 Java 9 版本引入的新特性。涉及到 ImmutableCollections 类。

List.ofList.copyOf 静态工厂方法提供了一种创建不可修改列表的便捷方式。

通过这些方法创建的 List 实例具有以下特点: 它们是不可修改的。不能添加、移除或替换元素。在列表上调用任何修改方法总是会导致抛出 UnsupportedOperationException 异常。然而,如果包含的元素本身是可变的,这可能会使列表的内容看起来发生了变化。

它们不允许 null 元素。尝试用null元素创建它们会导致NullPointerException

如果所有元素都是可序列化的,它们就是可序列化的。

列表中元素的顺序与提供的参数的顺序或提供的数组中元素的顺序相同。这些列表及其子列表视图实现了 RandomAccess 接口。 它们是基于值的。编码人员应该将相等的实例视为可互换的,并且不应该将它们用于同步,否则可能会发生不可预测的行为。例如,在未来的版本中,同步可能会失败。调用者不应该对返回的实例的标识做任何假设。工厂可以自由地创建新实例或重用现有的实例。 它们按照“序列化形式”页面上的指定进行序列化。

相关链接

Collection | z2huo

迭代器 ListIterator | z2huo

迭代器 Iterator | z2huo

[[Iterable]]

[[Collection]]

[[迭代器 ListIterator]]

[[迭代器 Iterator]]

OB tags

#Java