Java List原理示例源码详解
原理
List接口是Java集合框架中的一部分,它定义了一种有序的集合,可以按照索引访问元素并支持元素的插入、删除和搜索操作。
List接口的原理主要包括以下几个方面:
-
数据结构:List接口的实现类通常使用数组、链表或其他数据结构来存储元素。具体选择哪种数据结构取决于实现类的特点和需求。例如,ArrayList使用动态数组来存储元素,LinkedList使用双向链表。
-
索引访问:List接口通过整数索引提供对元素的访问。每个元素都有一个与之对应的索引,可以通过索引值来快速定位和访问元素。索引从0开始,表示列表中的第一个元素。
-
元素插入和删除:List接口提供了在指定位置插入和删除元素的方法。这些操作可能需要移动其他元素以保持顺序或调整内部数据结构,以便维护列表的正确性。
-
搜索操作:List接口提供了根据元素值进行搜索的方法,如
indexOf()
和lastIndexOf()
。这些方法通常需要遍历列表来查找匹配的元素,时间复杂度为O(n)。 -
迭代器:List接口提供了迭代器(Iterator)用于遍历列表中的元素。迭代器提供了一种简单而统一的方式来访问列表中的元素,可以逐个地获取元素并进行相应的操作。
-
接口约定:List接口对继承自Collection接口的方法进行了额外的约定和规范,例如
add()
、remove()
、equals()
和hashCode()
等方法的行为和语义。
List接口的实现类根据具体的数据结构和算法选择,在性能、空间复杂度和特定操作上可能有所差异。Java中常见的List实现类包括ArrayList、LinkedList和Vector。
-
ArrayList:ArrayList是基于数组实现的动态数组。它内部使用一个数组来存储元素,当元素数量超过数组容量时,会自动扩容。在添加、删除和随机访问等操作上具有较好的性能,时间复杂度为O(1)或O(n)。但在插入和删除操作时需要移动元素,因此效率较低。
-
LinkedList:LinkedList是基于双向链表实现的。它内部的每个节点都包含了元素本身以及指向前一个节点和后一个节点的引用。在添加和删除操作上具有较好的性能,时间复杂度为O(1)。但随机访问的性能较差,需要遍历链表到达目标位置。
-
Vector:Vector是线程安全的动态数组,与ArrayList类似。它的实现方式与ArrayList基本相同,但在方法上添加了同步锁以保证线程安全。由于存在同步开销,性能上略低于ArrayList。
这些List的实现类都提供了对List接口定义的方法的具体实现。它们根据自身的数据结构特点,选择适合的算法来实现各种操作,以提供高效的列表操作功能。具体实现会根据添加、删除、查找等操作的特点进行优化,以提高性能和效率。同时,它们也会处理边界条件、容量管理、并发访问等问题,确保列表的正确性和可靠性。
示例
以下是List接口中各种方法的代码示例,并包含了输出结果:
- 查询操作:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
int size = list.size(); // 返回列表中的元素数量
System.out.println(size); // 输出:3
boolean isEmpty = list.isEmpty(); // 判断列表是否为空
System.out.println(isEmpty); // 输出:false
boolean contains = list.contains("apple"); // 判断列表是否包含指定元素
System.out.println(contains); // 输出:true
Iterator<String> iterator = list.iterator(); // 获取列表的迭代器
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element); // 输出:apple, banana, orange
}
Object[] array = list.toArray(); // 将列表转换为数组
System.out.println(Arrays.toString(array)); // 输出:[apple, banana, orange]
List<String> sublist = Arrays.asList("apple", "banana");
boolean containsAll = list.containsAll(sublist); // 判断列表是否包含指定集合中的所有元素
System.out.println(containsAll); // 输出:true
boolean equals = list.equals(sublist); // 判断列表是否与指定对象相等
System.out.println(equals); // 输出:false
int hashCode = list.hashCode(); // 返回列表的哈希码值
System.out.println(hashCode); // 输出:-1331087707
- 修改操作:
List<String> list = new ArrayList<>();
boolean added = list.add("apple"); // 将指定元素添加到列表的末尾
System.out.println(added); // 输出:true
boolean removed = list.remove("apple"); // 从列表中移除指定元素
System.out.println(removed); // 输出:true
List<String> sublist = Arrays.asList("banana", "orange");
boolean addedAll = list.addAll(sublist); // 将指定集合中的所有元素添加到列表的末尾
System.out.println(addedAll); // 输出:true
boolean removedAll = list.removeAll(sublist); // 从列表中移除包含在指定集合中的所有元素
System.out.println(removedAll); // 输出:true
boolean retainedAll = list.retainAll(sublist); // 仅保留列表中包含在指定集合中的元素,移除其他元素
System.out.println(retainedAll); // 输出:false
list.clear(); // 移除列表中的所有元素
System.out.println(list.isEmpty()); // 输出:true
- 位置访问操作:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
String element = list.get(1); // 返回列表中指定位置的元素
System.out.println(element); // 输出:banana
String previousElement = list.set(1, "cherry"); // 替换列表中指定位置的元素
System.out.println(previousElement); // 输出:banana
list.add(0, "pear"); // 在列表中指定位置插入元素
System.out.println(list.get(0)); // 输出:pear
String removedElement = list.remove(2); // 移除列表中指定位置的元素
System.out.println(removedElement); // 输出:orange
- 搜索操作:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
int index = list.indexOf("banana"); // 返回指定元素在列表中第一次出现的索引
System.out.println(index); // 输出:1
int lastIndex = list.lastIndexOf("banana"); // 返回指定元素在列表中最后一次出现的索引
System.out.println(lastIndex); // 输出:1
- 列表迭代器:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
ListIterator<String> iterator = list.listIterator();
// 正向遍历列表并在特定条件下插入新元素
while (iterator.hasNext()) {
String element = iterator.next();
if (element.equals("banana")) {
iterator.add("grape"); // 在当前元素之前插入新元素
}
}
System.out.println(list); // 输出:[apple, grape, banana, orange]
// 反向遍历列表并替换指定元素
while (iterator.hasPrevious()) {
String element = iterator.previous();
if (element.equals("grape")) {
iterator.set("mango"); // 替换当前元素的值
}
}
System.out.println(list); // 输出:[apple, mango, banana, orange]
// 删除特定元素
while (iterator.hasNext()) {
String element = iterator.next();
if (element.equals("banana")) {
iterator.remove(); // 移除当前元素
}
}
System.out.println(list); // 输出:[apple, mango, orange]
- 视图操作:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
List<String> sublist = list.subList(0, 2); // 返回列表中指定范围的视图
System.out.println(sublist); // 输出:[apple, banana]
- 其他操作:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
// 创建一个Spliterator,用于遍历列表中的元素
Spliterator<String> spliterator = list.spliterator();
// 使用tryAdvance方法迭代处理每个元素,如果还有下一个元素则返回true
while (spliterator.tryAdvance(element -> {
System.out.println(element); // 打印当前元素
})) {
System.out.println(1); // 打印1,表示还有下一个元素
}
// 输出:
// apple
// 1
// banana
// 1
// orange
// 1
方法总结
List接口定义了以下方法:
-
查询操作:
int size()
:返回列表中的元素数量。boolean isEmpty()
:判断列表是否为空。boolean contains(Object o)
:判断列表是否包含指定元素。Iterator<E> iterator()
:返回列表的迭代器。Object[] toArray()
:将列表转换为数组。boolean containsAll(Collection<?> c)
:判断列表是否包含指定集合中的所有元素。boolean equals(Object o)
:判断列表是否与指定对象相等。int hashCode()
:返回列表的哈希码值。
-
修改操作:
boolean add(E e)
:将指定元素添加到列表的末尾。boolean remove(Object o)
:从列表中移除指定元素。boolean addAll(Collection<? extends E> c)
:将指定集合中的所有元素添加到列表的末尾。boolean removeAll(Collection<?> c)
:从列表中移除包含在指定集合中的所有元素。boolean retainAll(Collection<?> c)
:仅保留列表中包含在指定集合中的元素,移除其他元素。void clear()
:移除列表中的所有元素。
-
位置访问操作:
E get(int index)
:返回列表中指定位置的元素。E set(int index, E element)
:替换列表中指定位置的元素。void add(int index, E element)
:在列表中指定位置插入元素。E remove(int index)
:移除列表中指定位置的元素。
-
搜索操作:
int indexOf(Object o)
:返回指定元素在列表中第一次出现的索引。int lastIndexOf(Object o)
:返回指定元素在列表中最后一次出现的索引。
-
列表迭代器:
ListIterator<E> listIterator()
:返回列表的列表迭代器。ListIterator<E> listIterator(int index)
:从指定位置开始返回列表的列表迭代器。
-
视图操作:
List<E> subList(int fromIndex, int toIndex)
:返回列表中指定范围的视图。
-
其他操作:
Spliterator<E> spliterator()
:创建一个Spliterator,用于遍历列表中的元素。
注意:列表迭代器适用于需要在遍历列表时进行元素插入、替换、删除等操作的场景。与普通的迭代器相比,列表迭代器提供了更多的功能和灵活性。
适用场景包括:
-
双向遍历:列表迭代器可以从列表的任意方向进行遍历,通过
previous()
方法向前遍历,通过next()
方法向后遍历。 -
元素修改:列表迭代器提供了
set(E e)
方法,可以替换当前元素的值,并且可以使用add(E e)
方法在当前位置之前插入一个新元素。 -
删除元素:列表迭代器提供了
remove()
方法,可以移除当前位置上的元素。不同于普通迭代器的remove()
方法,列表迭代器的remove()
方法在执行后仍然可以继续遍历其他元素。 -
定位操作:列表迭代器提供了
nextIndex()
和previousIndex()
方法,可以获取当前迭代器所在位置的索引值。 -
并发修改:列表迭代器支持在迭代过程中对列表进行并发修改。与普通迭代器不同,列表迭代器的修改操作不会抛出
ConcurrentModificationException
异常。
由于列表迭代器具有双向遍历和元素修改的能力,适用于需要在迭代过程中对列表进行复杂操作的场景。例如,需要遍历一个有序列表并根据某些条件插入、删除或替换元素时,列表迭代器可以提供方便和高效的实现方式。
总而言之,列表迭代器适用于需要在遍历列表时进行双向遍历、元素修改、插入和删除等操作的场景。它提供了更灵活的功能,使开发人员能够更方便地操作和管理列表中的元素。
中文源码
以下是给List
接口添加中文注释的源代码:
/**
* 有序集合(也称为<i>序列</i>)。该接口的用户可以精确控制元素在列表中的插入位置。
* 用户可以通过整数索引(在列表中的位置)访问元素,并在列表中搜索元素。<p>
*
* 与集合不同,列表通常允许重复的元素。更正式地说,列表通常允许成对的元素<tt>e1</tt>和<tt>e2</tt>,
* 这样<tt>e1.equals(e2)</tt>,如果允许空元素,则通常允许多个null元素。
* 当然,也可以实现禁止重复的列表,当用户尝试插入重复元素时,会抛出运行时异常,但我们预计这种用法很少见。<p>
*
* <tt>List</tt>接口在<tt>Collection</tt>接口指定的契约之外,还对<tt>iterator</tt>、<tt>add</tt>、
* <tt>remove</tt>、<tt>equals</tt>和<tt>hashCode</tt>方法的契约提供了额外的规定。
* 在这里还包括其他继承方法的声明,以方便使用。<p>
*
* <tt>List</tt>接口提供了四种方法来对列表元素进行位置(索引)访问。
* 列表(如Java数组)从零开始。请注意,对于某些实现(例如<tt>LinkedList</tt>类),
* 这些操作的执行时间可能与索引值成比例。因此,如果调用方不知道实现细节,
* 通常优选通过迭代列表中的元素而不是通过索引访问它。<p>
*
* <tt>List</tt>接口提供了一种特殊的迭代器,称为<tt>ListIterator</tt>,
* 它允许插入和替换元素,并支持双向访问,除了<tt>Iterator</tt>接口提供的常规操作之外。
* 提供了一种方法来获取从列表中指定位置开始的列表迭代器。<p>
*
* <tt>List</tt>接口提供了两种搜索指定对象的方法。从性能的角度来看,应该谨慎使用这些方法。
* 在许多实现中,它们将执行昂贵的线性搜索。<p>
*
* <tt>List</tt>接口提供了两种高效地在列表的任意位置插入和删除多个元素的方法。<p>
*
* 注意:虽然允许列表包含自身作为元素,但建议极度小心:在这种列表上,
* <tt>equals</tt>和<tt>hashCode</tt>方法不再定义良好。<p>
*
* 一些列表实现对它们可以包含的元素有限制。例如,某些实现禁止空元素,
* 有些对元素的类型有限制。尝试添加不合格的元素会抛出未经检查的异常,
* 通常是<tt>NullPointerException</tt>或<tt>ClassCastException</tt>。
* 尝试查询不合格元素的存在可能会抛出异常,或者它可能只返回false;
* 某些实现将表现为前一种行为,某些实现将表现为后一种行为。
* 更一般地说,对于在列表中插入不合格元素的完成不会导致
* 不合格元素插入到列表中的操作的尝试可能会抛出异常,也可能会成功,具体取决于实现的选择。
* 在此接口的规范中,这些异常被标记为“可选”。
*
* <p>此接口是
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java集合框架</a>的成员。
*
* @param <E> 此列表中元素的类型
* @see Collection
* @see Set
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Arrays#asList(Object[])
* @see Collections#nCopies(int, Object)
* @see Collections#EMPTY_LIST
* @see AbstractList
* @see AbstractSequentialList
* @since 1.2
*/
public interface List<E> extends Collection<E> {
// 查询操作
/**
* 返回列表中元素的数量。如果列表包含超过Integer.MAX_VALUE个元素,则返回Integer.MAX_VALUE。
*
* @return 列表中元素的数量
*/
int size();
/**
* 判断列表是否为空。
*
* @return 如果列表不包含任何元素,则返回true
*/
boolean isEmpty();
/**
* 判断列表是否包含指定的元素。
*
* @param o 要在列表中测试存在性的元素
* @return 如果列表包含至少一个等于o的元素,则返回true
* @throws ClassCastException 如果指定元素的类型与列表中元素的类型不兼容(可选)
* @throws NullPointerException 如果指定元素为null且列表不允许null元素(可选)
*/
boolean contains(Object o);
/**
* 返回一个迭代器,用于按正确顺序遍历列表中的元素。
*
* @return 以正确顺序遍历列表中的元素的迭代器
*/
Iterator<E> iterator();
/**
* 返回一个包含列表中所有元素的数组,按照从第一个到最后一个元素的顺序排列。
*
* <p>返回的数组是“安全的”,即对它的引用不会被列表保持。(换句话说,即使该列表由数组支持,此方法也必须分配一个新的数组)。
* 调用者可以自由地修改返回的数组。
*
* <p>此方法充当数组和基于集合的API之间的桥梁。
*
* @return 包含列表中所有元素的数组,按照从第一个到最后一个元素的顺序排列
* @see Arrays#asList(Object[])
*/
Object[] toArray();
/**
* 返回一个包含列表中所有元素的数组,按照从第一个到最后一个元素的顺序排列;
* 返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,
* 则将其返回;否则,将为此目的分配一个具有指定数组的运行时类型和此列表的大小的新数组。
*
* <p>如果列表适合指定的数组,并且还有空余空间(即数组的长度大于列表的大小),
* 则数组中紧接在列表结束之后的元素将设置为null。
* (这仅在调用者知道列表不包含任何null元素时才有用,只要调用者知道列表不包含任何null元素,就可以确定列表的长度)
*
* <p>与{@link #toArray()}方法一样,此方法充当数组和基于集合的API之间的桥梁。
* 此外,此方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下可以用于节省分配成本。
*
* <p>假设x是一个已知仅包含字符串的列表。
* 下面的代码可用于将列表转储到新分配的String数组中:
*
* <pre>{@code
* String[] y = x.toArray(new String[0]);
* }</pre>
*
* 注意,<tt>toArray(new Object[0])</tt>在功能上与<tt>toArray()</tt>相同。
*
* @param a 存储列表元素的数组,如果它足够大;否则,将为此目的分配一个具有指定数组的运行时类型和列表大小的新数组。
* @return 包含列表元素的数组
* @throws ArrayStoreException 如果指定数组的运行时类型不是列表中每个元素的超类型
* @throws NullPointerException 如果指定数组为null
*/
<T> T[] toArray(T[] a);
// 修改操作
/**
* 将指定的元素追加到列表的末尾(可选操作)。
*
* <p>支持此操作的列表可能对可以添加到列表的元素有限制。特别是,某些列表将拒绝添加null元素,
* 而其他列表将对可以添加的元素类型施加限制。列表类应在其文档中明确指定可以添加哪些元素的限制。
*
* @param e 要追加到列表末尾的元素
* @return 始终返回true(根据{@link Collection#add}的规范)
* @throws UnsupportedOperationException 如果此列表不支持<tt>add</tt>操作
* @throws ClassCastException 如果指定元素的类阻止将其添加到此列表
* @throws NullPointerException 如果指定元素为null且此列表不允许null元素
* @throws IllegalArgumentException 如果指定元素的某些属性阻止将其添加到此列表
*/
boolean add(E e);
/**
* 如果存在,则从该列表中移除指定元素的第一个匹配项(可选操作)。
* 如果列表不包含该元素,则它将保持不变。更正式地说,
* 移除最低索引<i>i</i>的元素,使得
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (如果存在这样的元素)。(如果存在这样的元素)返回<tt>true</tt>;
* 如果此列表未更改,则返回<tt>false</tt>。
*
* @param o 要从此列表中移除的元素(如果存在)
* @return 如果列表包含指定的元素,则返回<tt>true</tt>
* @throws ClassCastException 如果指定元素的类型与此列表不兼容(可选)
* @throws NullPointerException 如果指定元素为null且此列表不允许null元素(可选)
* @throws UnsupportedOperationException 如果此列表不支持<tt>remove</tt>操作
*/
boolean remove(Object o);
// 批量修改操作
/**
* 返回<tt>true</tt>如果此列表包含指定集合的所有元素。
*
* @param c 要在此列表中检查其包含性的集合
* @return 如果此列表包含指定集合的所有元素,则返回<tt>true</tt>
* @throws ClassCastException 如果指定集合的一个或多个元素的类型与此列表不兼容(可选)
* @throws NullPointerException 如果指定集合包含一个或多个null元素且此列表不允许null元素
* (<a href="Collection.html#optional-restrictions">可选</a>),
* 或者指定集合为null
* @see #contains(Object)
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合中的所有元素按照指定集合的迭代器返回的顺序追加到该列表的末尾(可选操作)。
* 如果在操作进行过程中修改了指定的集合(除非是通过迭代器自身的<tt>remove</tt>操作),
* 那么操作的结果是不确定的。(注意,如果指定的集合是此列表,并且它是非空的,
* 那么这将发生)。
*
* @param c 包含要添加到此列表的元素的集合
* @return 如果调用后此列表发生更改,则返回<tt>true</tt>
* @throws UnsupportedOperationException 如果此列表不支持<tt>addAll</tt>操作
* @throws ClassCastException 如果指定集合中的一个或多个元素的类阻止将其添加到此列表
* @throws NullPointerException 如果指定集合包含一个或多个null元素且此列表不允许null元素,
* 或者指定集合为null
* @throws IllegalArgumentException 如果指定集合中的某个元素的某些属性阻止将其添加到此列表
* @see #add(Object)
*/
boolean addAll(Collection<? extends E> c);
/**
* 将指定集合中的所有元素插入到此列表的指定位置(可选操作)。
* 当前位于该位置的元素(如果有)和任何后续元素都会向右移动(增加其索引)。
* 新元素将按照它们由指定集合的迭代器返回的顺序出现在此列表中。
* 如果在操作进行过程中修改了指定的集合(除非是通过迭代器自身的<tt>remove</tt>操作),
* 那么操作的结果是不确定的。(注意,如果指定的集合是此列表,并且它是非空的,
* 那么这将发生)。
*
* @param index 要插入指定集合中第一个元素的索引
* @param c 包含要添加到此列表的元素的集合
* @return 如果调用后此列表发生更改,则返回<tt>true</tt>
* @throws UnsupportedOperationException 如果此列表不支持<tt>addAll</tt>操作
* @throws ClassCastException 如果指定集合中的一个或多个元素的类阻止将其添加到此列表
* @throws NullPointerException 如果指定集合包含一个或多个null元素且此列表不允许null元素,
* 或者指定集合为null
* @throws IllegalArgumentException 如果指定集合中的某个元素的某些属性阻止将其添加到此列表
* @throws IndexOutOfBoundsException 如果索引超出范围(<tt>index < 0 || index > size()</tt>)
*/
boolean addAll(int index, Collection<? extends E> c);
/**
* 从此列表中移除在指定集合中存在的所有元素(可选操作)。
*
* @param c 包含要从此列表中移除的元素的集合
* @return 如果调用后此列表发生更改,则返回<tt>true</tt>
* @throws UnsupportedOperationException 如果此列表不支持<tt>removeAll</tt>操作
* @throws ClassCastException 如果此列表中的某个元素与指定集合中的某个元素的类型不兼容(可选)
* @throws NullPointerException 如果此列表包含一个null元素且指定集合不允许null元素(可选),
* 或者指定集合为null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean removeAll(Collection<?> c);
/**
* 仅保留在此列表中同时存在于指定集合中的元素(可选操作)。
* 换句话说,移除列表中不包含在指定集合中的所有元素。
*
* @param c 包含要在此列表中保留的元素的集合
* @return 如果调用后此列表发生更改,则返回<tt>true</tt>
* @throws UnsupportedOperationException 如果此列表不支持<tt>retainAll</tt>操作
* @throws ClassCastException 如果此列表中的某个元素与指定集合中的某个元素的类型不兼容(可选)
* @throws NullPointerException 如果此列表包含一个null元素且指定集合不允许null元素(可选),
* 或者指定集合为null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean retainAll(Collection<?> c);
/**
* 使用操作符对列表中的每个元素进行替换。
* 操作符引发的错误或运行时异常将传递给调用者。
*
* @implSpec
* 默认实现相当于以下代码:
* <pre>{@code
* final ListIterator<E> li = list.listIterator();
* while (li.hasNext()) {
* li.set(operator.apply(li.next()));
* }
* }</pre>
*
* 如果列表的列表迭代器不支持<tt>set</tt>操作,
* 那么在替换第一个元素时将抛出<tt>UnsupportedOperationException</tt>异常。
*
* @param operator 要应用于每个元素的操作符
* @throws UnsupportedOperationException 如果此列表是不可修改的。
* 如果无法替换元素或者一般情况下不支持修改,则实现可能会抛出此异常
* @throws NullPointerException 如果指定的操作符为null,
* 或者如果操作符的结果为null值且此列表不允许null元素
* (<a href="Collection.html#optional-restrictions">可选</a>)
* @since 1.8
*/
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
* 根据指定的{@link Comparator}对此列表进行排序。
*
* <p>此列表中的所有元素都必须是<i>可相互比较的</i>,
* 使用指定的比较器(即,对于列表中的每个元素<tt>e1</tt>和<tt>e2</tt>,
* <tt>c.compare(e1, e2)</tt>不会抛出<tt>ClassCastException</tt>)。
*
* <p>如果指定的比较器为null,则此列表中的所有元素必须实现{@link Comparable}接口,
* 并且应使用元素的{@linkplain Comparable natural ordering}。
*
* <p>此列表必须是可修改的,但不一定是可调整大小的。
*
* @implSpec
* 默认实现创建一个包含该列表中所有元素的数组,对数组进行排序,并遍历该列表,
* 将数组中的每个元素按照相应位置设置到列表中。
* (这避免了在原地对链表进行排序时可能产生的O(n^2 log(n))性能问题)
*
* @implNote
* 此实现是一个稳定、自适应、迭代合并排序算法。当输入数组部分排序时,
* 它需要远少于n lg(n)次比较,同时提供了传统归并排序的性能。
* 如果输入数组几乎已经排序,则该实现需要大约n次比较。
* 临时存储需求从几乎排序的输入数组的小常数变为随机排序的输入数组的n/2个对象引用。
*
* <p>该实现采用了Python中Tim Peters的列表排序算法
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
* TimSort</a>)的技术。它使用了Peter McIlroy的“Optimistic Sorting and Information Theoretic Complexity”
* 论文中的技术,发表在第四届ACM-SIAM离散算法年会的论文集中,第467-474页,1993年1月。
*
* @param c 用于比较列表元素的{@code Comparator}。如果指定的比较器为null,
* 则使用元素的{@linkplain Comparable natural ordering}
* @throws ClassCastException 如果列表包含与指定集合中的某些元素不可相互比较的元素
* @throws UnsupportedOperationException 如果列表的列表迭代器不支持<tt>set</tt>操作
* @throws IllegalArgumentException
* (<a href="Collection.html#optional-restrictions">可选</a>)
* 如果发现比较器违反了{@link Comparator}约定
* @since 1.8
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
/**
* 从列表中移除所有元素(可选操作)。
* 此调用返回后,列表将变为空。
*
* @throws UnsupportedOperationException 如果此列表不支持clear操作
*/
def clear(): Unit
// 比较和哈希
/**
* 将指定对象与此列表进行比较,判断是否相等。如果指定对象也是一个列表,
* 并且两个列表的大小相同,并且两个列表对应位置的元素都相等,则返回true。
* (两个元素e1和e2相等的条件是:e1==null ? e2==null : e1.equals(e2))。
* 换句话说,如果两个列表以相同顺序包含相同的元素,则定义它们为相等。
* 这个定义确保equals方法在List接口的不同实现之间正常工作。
*
* @param o 要与此列表进行比较的对象
* @return 如果指定对象等于此列表,则返回true
*/
def equals(o: Object): Boolean
/**
* 返回此列表的哈希码值。列表的哈希码定义为以下计算结果:
* <pre>{@code
* int hashCode = 1;
* for (E e : list)
* hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
* }</pre>
* 这样可以确保对于任何两个列表list1和list2,
* 如果list1.equals(list2),则list1.hashCode()==list2.hashCode(),
* 根据Object.hashCode的通用合同要求。
*
* @return 此列表的哈希码值
*/
def hashCode(): Int
// 位置访问操作
/**
* 返回此列表中指定位置的元素。
*
* @param index 要返回的元素的索引
* @return 此列表中指定位置的元素
* @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index >= size())
*/
def get(index: Int): E
/**
* 将此列表中指定位置的元素替换为指定元素(可选操作)。
*
* @param index 要替换的元素的索引
* @param element 要存储在指定位置的元素
* @return 先前位于指定位置的元素
* @throws UnsupportedOperationException 如果此列表不支持set操作
* @throws ClassCastException 如果指定元素的类阻止将其添加到此列表中
* @throws NullPointerException 如果指定元素为null,而此列表不允许null元素
* @throws IllegalArgumentException 如果指定元素的某些属性阻止将其添加到此列表中
* @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index >= size())
*/
def set(index: Int, element: E): E
/**
* 在此列表的指定位置插入指定元素(可选操作)。
* 将当前位于该位置(如果有)和任何后续元素右移(索引加一)。
*
* @param index 要插入指定元素的索引
* @param element 要插入的元素
* @throws UnsupportedOperationException 如果此列表不支持add操作
* @throws ClassCastException 如果指定元素的类阻止将其添加到此列表中
* @throws NullPointerException 如果指定元素为null,而此列表不允许null元素
* @throws IllegalArgumentException 如果指定元素的某些属性阻止将其添加到此列表中
* @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index > size())
*/
def add(index: Int, element: E): Unit
/**
* 移除此列表中指定位置的元素(可选操作)。
* 后续元素左移(索引减一)。返回从列表中删除的元素。
*
* @param index 要删除的元素的索引
* @return 先前位于指定位置的元素
* @throws UnsupportedOperationException 如果此列表不支持remove操作
* @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index >= size())
*/
def remove(index: Int): E
// 搜索操作
/**
* 返回此列表中指定元素第一次出现的索引,如果此列表不包含该元素,则返回-1。
* 更正式地说,返回最低的索引i,使得(o==null ? get(i)==null : o.equals(get(i))),
* 如果没有这样的索引,则返回-1。
*
* @param o 要搜索的元素
* @return 此列表中指定元素第一次出现的索引,如果此列表不包含该元素,则返回-1
* @throws ClassCastException 如果指定元素的类型与此列表不兼容
* (可选)
* @throws NullPointerException 如果指定元素为null,而此列表不允许null元素
* (可选)
*/
def indexOf(o: Object): Int
/**
* 返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-1。
* 更正式地说,返回最高的索引i,使得(o==null ? get(i)==null : o.equals(get(i))),
* 如果没有这样的索引,则返回-1。
*
* @param o 要搜索的元素
* @return 此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-1
* @throws ClassCastException 如果指定元素的类型与此列表不兼容
* (可选)
* @throws NullPointerException 如果指定元素为null,而此列表不允许null元素
* (可选)
*/
def lastIndexOf(o: Object): Int
// 列表迭代器
/**
* 返回此列表中元素的列表迭代器(按适当顺序)。
*
* @return 此列表中元素的列表迭代器(按适当顺序)
*/
def listIterator(): ListIterator[E]
/**
* 返回此列表中元素的列表迭代器(按适当顺序),从列表中指定位置开始。
* 指定的索引表示初始调用{@link ListIterator#next next}将返回的第一个元素。
* 初始调用{@link ListIterator#previous previous}将返回具有指定索引减一的元素。
*
* @param index 要从列表迭代器中返回的第一个元素的索引
* @return 此列表中元素的列表迭代器(按适当顺序),从列表中指定位置开始
* @throws IndexOutOfBoundsException 如果索引超出范围(index < 0 || index > size())
*/
def listIterator(index: Int): ListIterator[E]
// 视图
/**
* 返回此列表中从指定的fromIndex(包括)到指定的toIndex(不包括)的部分的视图。
* (如果fromIndex和toIndex相等,则返回的列表为空。)
* 返回的列表由此列表支持,因此在返回的列表中进行的非结构性更改将反映在此列表中,反之亦然。
* 返回的列表支持此列表支持的所有可选列表操作。<p>
*
* 此方法消除了对显式范围操作(通常适用于数组)的需求。
* 可以通过传递子列表视图而不是整个列表来使用期望列表的任何操作。
* 例如,以下惯用语从列表中删除一系列元素:
* <pre>{@code
* list.subList(from, to).clear();
* }</pre>
* 可以为indexOf和lastIndexOf构造类似的惯用语,
* 所有Collections类中的算法都可以应用于子列表。<p>
*
* 如果后台列表(即此列表)以任何方式进行结构修改,则此方法返回的列表的语义将变为未定义。
* (结构修改是指更改此列表的大小,或以其他方式扰乱它,使进行中的迭代可能产生不正确的结果。)
*
* @param fromIndex 子列表的起始端点(包括)
* @param toIndex 子列表的结束端点(不包括)
* @return 此列表中指定范围的视图
* @throws IndexOutOfBoundsException 对于非法的端点索引值
* (fromIndex < 0 || toIndex > size ||
* fromIndex > toIndex)
*/
def subList(fromIndex: Int, toIndex: Int): List[E]
/**
* 在该列表上创建一个Spliterator。
*
* <p> Spliterator报告SIZED和ORDERED。
* 实现应记录其他特征值的报告。
*
* @implSpec
* 默认实现从列表的Iterator创建一个延迟绑定的Spliterator。
* Spliterator继承了列表迭代器的快速失败属性。
*
* @implNote
* 创建的Spliterator还会报告SUBSIZED。
*
* @return 这个列表中元素的Spliterator
* @since 1.8
*/
override def spliterator(): Spliterator[E] = {
Spliterators.spliterator(this, Spliterator.ORDERED)
}