List简介
list
:集合中的元素按照索引的位置排序,集合中的元素可以重复,可以为null,允许按照对象在集合中的索引位置检索对象,遍历的顺序和放入的顺序是一致的。
List接口的定义
List的定义如下:
public interface List<E> extends Collection<E> {
//省略了Collection接口中已有的方法
/**
* 添加集合到指定的位置
*/
boolean addAll(int index, Collection<? extends E> c);
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
* 排序
*/
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);
}
}
/**
* 获取指定位置的元素
*/
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);
/**
*用于list 的迭代器
* 类似于标准的迭代器
*/
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
/**
* 截取list
*/
List<E> subList(int fromIndex, int toIndex);
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
AbstractList
AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。
public interface List<E> extends Collection<E> {
//省略了Collection接口中已有的方法
/**
* 添加集合到指定的位置
*/
boolean addAll(int index, Collection<? extends E> c);
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
* 排序
*/
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);
}
}
/**
* 获取指定位置的元素
*/
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
*/
List<E> subList(int fromIndex, int toIndex);
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。
上面的方法为list中特有的方法,上面的方法主要是位置相关的,因为list是带有下标的。
AbstractList
AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
protected AbstractList() {
}
//默认添加在最后的位置
public boolean add(E e) {
add(size(), e);
return true;
}
/**
* 修改指定位置的元素
* @param index
* @param element
*/
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* 添加到指定的位置
*/
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
//真正的list类实现
public E remove(int index) {
throw new UnsupportedOperationException();
}
/**
* 获取指定位置的元素
*/
abstract public E get(int index);
/**返回第一次出现o的索引
* 1、判断o是否是null
* 2、true集合中是否有null的元素,如果有则返回迭代器的上一位置
* 3、false 判断集合中是否有和o相等的元素,如果有则返回迭代器的上一位置
* 4、如果没有相同的则返回-1.
*/
public int indexOf(Object o) {
ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return it.previousIndex();
} else {
while (it.hasNext())
if (o.equals(it.next()))
return it.previousIndex();
}
return -1;
}
/**
* 返回最后o在集合中最后出现的位置
* 此处是通过,listIterator的逆序来实现的
*/
public int lastIndexOf(Object o) {
ListIterator<E> it = listIterator(size());
if (o==null) {
while (it.hasPrevious())
if (it.previous()==null)
return it.nextIndex();
} else {
while (it.hasPrevious())
if (o.equals(it.previous()))
return it.nextIndex();
}
return -1;
}
public void clear() {
removeRange(0, size());
}
/**
* 在指定的索引位置开始放入集合,原来位置的元素依次顺移,
* index介于0和size之间
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
public Iterator<E> iterator() {
return new Itr();
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
private class Itr implements Iterator<E> {
//具体实现稍后详细分析
}
private class ListItr extends Itr implements ListIterator<E> {
//待详细分析
}
//该SubLsit是ArrayList的内部类,它与ArrayList一样,都是继承AbstractList和实现RandomAccess接口
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
/**
*
*/
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
//l = list;而list就是在前面传递过来的list,也就是说l 就是原始list的引用。
// 同时在构造函数中它甚至将modCount(fail-fast机制)传递过来了 ") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
//其他方法的实现都是依赖AbstractList中的实现
}
//表明支持随机访问
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
}
内部类Itr源码分析
private class Itr implements Iterator<E> {
/**
*当前迭代器的位置,初始化的时候位于0索引的左边,调用next后位于索引0和1之间
* cursor对于每次调用next方法就增加一次
*/
int cursor = 0;
/**
* 上一个cursor的值就等于lastRet(用于删除操作)每次跳过的元素的坐标
*/
int lastRet = -1;
/**
* 迭代器在进行结构性的操作的时候expectedModCount加一
*/
int expectedModCount = modCount;
/**
* 是否是最后一个元素
* 1、比较cursor的值和size的大小。如果两者相等则说明迭代到尾了。
*/
public boolean hasNext() {
return cursor != size();
}
/**
* 返回的是光标经过的上一个索引的元素
* 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
* 2、i = cursor 记录光标的位置
* 3、 获取光标经过的元素
* 4、lastRet = i 前一个元素对应的光标
* 5、光标加1
*
*/
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
/**
* 一个remove之前必须要有一个next
* 删除光标经过的的元素
* 1、判断上一个光标的位置,有2中情况等于-1
* 1、1 初始化的时候没有调用next方法,直接调用remove方法
* 1.2 连续2次调用remove方法
* 2、 调用ArrayList本身的remove()方法删除lastRet位置元素
* 3、修改cursor和lastRet
* 4、修改expectedModCount
*
*/
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
modCount在list、map、set中都有这个参数,这个参数的作用是记录修改的次数。
使用modCount属性的集合全是全是线程不安全的,
在一个迭代器初始的时候会赋予它调用这个迭代器的对象的mCount,如何在迭代器遍历的过程中,一旦发现这个对象的mcount和迭代器中存储的mcount不一样那就抛异常
就是fail-fast
内部类ListItr源码分析
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
/**
* 如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false
* 根据cursor=0,为迭代器初始化的位置。
*/
public boolean hasPrevious() {
return cursor != 0;
}
/**
* 返回游标左边的元素
* 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
* 2、i = cursor-1 记录光标左边元素的索引
* 3、 根据索引获取,光标左边的元素
* 4、 lastRet = cursor = i修改光标跳过的元素的索引
*/
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
/**
*返回调用next后所返回元素的索引
*/
public int nextIndex() {
return cursor;
}
/**
* 返回调用previous后所返回元素的索引。
*/
public int previousIndex() {
return cursor-1;
}
/**
* 用指定元素替换 next 或 previous 返回的元素
* 1、判断光标经过的元素坐标是否为-1(迭代器初始化的时候,或者连续2次调用修改结构性的方法)
* 2、 调用AbstractList的set
* 3、修改expectedModCount
*/
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
/**
* 将指定的元素插入列表
* 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
* 2、将元素插入到光标的后边
* 3、发生了结构性的修改,lastRet重置为-1
* 4、将光标向右移动一位
* 5、 修改expectModCount
*/
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
// Comparison and hashing
/**
* 比较两个集合是否相同
*/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
protected transient int modCount = 0;
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size())
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size();
}
}
ListItr实现了ListIterator接口同时继承了Itr,此接口是Iterator接口的扩展,使迭代器不但可以向后遍历,也可以向前遍历,还可以获取将要遍历元素的下标,
和当前元素的下标,同时可以通过迭代器对元素进行添加、删除、修改的操作
SubList
//该SubLsit是ArrayList的内部类,它与ArrayList一样,都是继承AbstractList和实现RandomAccess接口
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
/**
*
*/
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
//l = list;而list就是在前面传递过来的list,也就是说l 就是原始list的引用。
// 同时在构造函数中它甚至将modCount(fail-fast机制)传递过来了 ") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
//其他方法的实现都是依赖AbstractList中的实现
}
它返回原来list的从[fromIndex, toIndex)之间这一部分的视图,之所以说是视图,是因为实际上,返回的list是靠原来的list支持的。
如果发生结构性修改的是返回的子list,那么原来的list的大小也会发生变化;
而如果发生结构性修改的是原来的list(不包括由于返回的子list导致的改变),那么返回的子list语义上将会是undefined。在AbstractList(ArrayList的父类)中,undefined的具体表现形式是抛出一个ConcurrentModificationException。