List源码分析
简介
我们平常用的最多的就是list了,就是一个集成了Collection接口的接口。我们先大概的了解一下的它的API:
对于Collection中的接口不再做分析,可以参照这篇:Colleciton 接口源码分析
本节重点API
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()));
}
}
@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);
}
}
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);
ListIterator源码分析
ListIterator简介
ListIterator 源码分析
// Iterator中存在的接口就不分析了,可以看我的Itearor的分析
public interface ListIterator<E> extends Iterator<E> {
// 反向遍历列表,向前遍历,判断前面是否有元素,如果有,为true
boolean hasPrevious();
// 返回前面元素
E previous();
// 返回下一个元素的索引 最后一个为size-1
int nextIndex();
// 返回前一个元素索引,第一个为0
int previousIndex();
// 移除元素
void remove();
// 设置元素
void set(E e);
// 添加元素
void add(E e);
}
ListIterator的使用注意点:
1:遍历的时候,it.next或者it.previous,控制游标后移或者迁移,如果不进行控制,可能会出错,比如死循环,set方法出错等等。
ArrayList<Integer> list=new ArrayList<Integer>();
for (int i = 0; i < 5; i++) {
list.add(i);
}
ListIterator<Integer> litr1 = list.listIterator();
// 光标会指向最后一个元素的后面
/*while (litr1.hasNext()){
System.out.println("向后遍历元素:"+ litr1.next());
}
// 我们现在可以向前遍历
while (litr1.hasPrevious()){
System.out.println("向前遍历元素"+litr1.previous());
}*/
// 注意这边一定要后移元素,不然会死循环
while (litr1.hasNext()){
System.out.println("返回下一个索引"+ litr1.nextIndex());
litr1.next();
}
// 向前遍历,返回前一个索引
while (litr1.hasPrevious()){
System.out.println("返回下一个索引"+ litr1.previousIndex());
litr1.previous();
}
List源码分析
-
boolean addAll(int index, Collection<? extends E> c)
1:在特定的位置插入集合(可选操作,不写特定位置,将会调用Colletion的addAll方法)
2:将当前位置的元素和后续的元素后移,并且增加索引
3:如果在在执行此操作的时候,被操作列表被修改了,那么这个增加的之后的结果是不确定的,就比如你添加进去的集合c就是被操作列表
-
default void replaceAll(UnaryOperator operator) {}
1:将该列表的每个元素替换为将运算符应用于该元素的结果
2:如果列表的ListIterator不支持set方法,则在替换第一个元素时就抛出UnsupportedOperationException异常
// 传入一个lambda表达式 default void replaceAll(UnaryOperator<E> operator) { // 对元素进行判空,如果为空抛出空指针异常 Objects.requireNonNull(operator); // 获取列表的ListIterator final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { // 对要替换的列表元素进行操作,并设置到要替换的列表中 li.set(operator.apply(li.next())); } }
-
default void sort(Comparator<? super E> c) {}
根据指定的顺序对此列表进行排序
default void sort(Comparator<? super E> c) { // 将集合转成数组 Object[] a = this.toArray(); // 调用Arrays.sort方法进行排序,返回排序后的数组 Arrays.sort(a, (Comparator) c); // 将排序后的数组的元素设置到集合中 ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }
-
普遍的增删获取API
// 获取指定索引位置的元素 E get(int index); // 设置指定元素到指定的索引位置 返回之前索引位置的元素 E set(int index, E element); // 在指定索引位置添加元素 void add(int index, E element); // 移除指定位置的元素,并返回此元素 E remove(int index); // 返回指定元素出现的第一次出现的索引,如果没有则返回-1 int indexOf(Object o); // 返回指定元素出现的最后一次索引,如果没有则返回-1 int lastIndexOf(Object o);
-
-
ListIterator listIterator(int index)
从指定位置开始,返回列表的迭代器
-
List subList(int fromIndex, int toIndex)
返回指定索引区间的列表视图
List<Integer> list=new ArrayList<Integer>(); for (int i = 0; i < 8; i++) { list.add(i); } // 返回指定索引区间的列表视图 List<Integer> listView = list.subList(0,3); for(Integer i : listView){ System.out.println(i); } System.out.println("--------------"); // 删除指定索引区间的元素 list.subList(0,3).clear(); for(Integer i : list){ System.out.println(i); }
-
default Spliterator spliterator() {}
- Spliterator既可以像Iterator那样逐个迭代,也可以批量迭代。批量迭代可以降低迭代的开销。
- Spliterator是可拆分的,一个Spliterator可以通过调用Spliterator trySplit()方法来尝试分成两个。一个是this,另一个是新返回的那个,这两个迭代器代表的元素没有重叠。
可通过(多次)调用Spliterator.trySplit()方法来分解负载,以便多线程处理。
// 并行遍历迭代器 @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, Spliterator.ORDERED); }