一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情。
indexOf
indexOf 方法主要用于查找元素在数组中的下标位置,如果元素存在就返回元素的下标位置,元素不存在的话返回 -1。并且支持 null 值的搜索,可以正向或者反向的查询。
正向查询源码:
private static int indexOf(Object o, Object[] elements,
int index, int fence) {
if (o == null) {
for (int i = index; i < fence; i++)
if (elements[i] == null)
return i;
} else {
for (int i = index; i < fence; i++)
if (o.equals(elements[i]))
return i;
}
return -1;
}
if (o == null) { } 可以对 null 进行搜索
if (elements[i] == null) return i; 找到第一个 null 值,返回下标索引的位置
for (int i = index; i < fence; i++) if (o.equals(elements[i])) return i;通过 equals 方法来判断元素是否相等,如果相等,返回元素的下标位置
入参o:需要搜索的元素
入参elements:我索的目标数组
入参index:搜索的开始位置
入参fence:搜索的结束位置
总结:
在进行元素是否存在的判断时,也就是contains方法,会使用到indexOf方法进行判断; 在删除元素的方法中,校验元素是否存在,也使用到indexOf方法; indexOf通过一次for循环来查找元素,在调用此方法时,需要注意如果找不到元素时,返回的是 -1,所以在实际使用时,有可能我们会对这个特殊值进行判断。
迭代
在其迭代过程中,即使数组的原值被改变,例如modCount发生改变,也不会抛出 ConcurrentModificationException异常,因为在于数组的每次变动,都会生成新的数组,不会影响老数组,这样的话,迭代过程中,根本就不会发生迭代数组的变动:
static final class COWIterator<E> implements ListIterator<E> {
private final Object[] snapshot;
private int cursor;
COWIterator(Object[] es, int initialCursor) {
this.cursor = initialCursor;
this.snapshot = es;
}
public boolean hasNext() {
return this.cursor < this.snapshot.length;
}
public boolean hasPrevious() {
return this.cursor > 0;
}
public E next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
} else {
return this.snapshot[this.cursor++];
}
}
public E previous() {
if (!this.hasPrevious()) {
throw new NoSuchElementException();
} else {
return this.snapshot[--this.cursor];
}
}
......
}
迭代过程中是直接持有原有数组的引用,假设原有数组的值内存地址发生变化,肯定会影响到迭代过程,而 CopyOnWriteArrayList 每次的数据变动,都会产生新的数组,对老数组的值不会产生影响,所以迭代也可以正常进行。
总结
如果需要在线程不安全场景下使用 List 时,可以使用 CopyOnWriteArrayList。