大家都看新闻了,最近石家庄疫情有新增。希望国际站能早日战胜!
踩坑迭代器
是不是有人在遍历删除List集合里的数据的时候遇到了某些问题?
简单用法
Collection<String> collection = new ArrayList<String>();
collection.add("Dao");
collection.add("Sen");
// 迭代器
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System. out.println(item);
// 打印完如果需要从集合删除
iterator.remove()
}
介绍常用的三个方法
- hasNext():返回boolean,表示判断是否存在下一个元素
- next():返回集合当前元素
- remove():删除当前元素
来看一下ArrayList的iterator实现方式
private class Itr implements Iterator<E> {
// 将要next返回元素的索引
int cursor = 0;
// 当前返回的元素的索引,初始值-1
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
// 由于cursor是将要返回元素的索引,也就是下一个元素的索引,和size比较是否相等,也就是判断是否已经next到最后一个元素
return cursor != size();
}
public E next() {
checkForComodification();
try {
// 根据下一个元素索引取出对应元素
E next = get( cursor);
// 更新lastRet为当前元素的索引,cursor加1
lastRet = cursor ++;
// 返回元素
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
// remove前必须先next一下,先取得当前元素
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList. this.remove(lastRet );
// 确保lastRet比cursor小、理论上永远lastRet比cursor小1
if (lastRet < cursor)
// 由于删除了一个元素cursor回退1
cursor--;
// 重置为-1
lastRet = -1;
expectedModCount = modCount ;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
再来看看LinkedList的Iterator实现
LinkedList的Iterator实现定义在AbstracSequentialtList中,实现在AbstractList中
AbstracSequentialtList的定义:
public Iterator<E> iterator() {
return listIterator();
}
AbstractList的实现:
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
if (index<0 || index>size())
throw new IndexOutOfBoundsException( "Index: "+index);
return new ListItr(index);
}
ListItr实现:
private class ListItr implements ListIterator<E> {
// 最后一次返回的节点,默认位header节点
private Entry<E> lastReturned = header;
// 将要返回的节点
private Entry<E> next ;
// 将要返回的节点index索引
private int nextIndex;
private int expectedModCount = modCount;
ListItr( int index) {
// 索引越界检查
if (index < 0 || index > size)
throw new IndexOutOfBoundsException( "Index: "+index+
", Size: "+size );
// 简单二分,判断遍历的方向
if (index < (size >> 1)) {
// 取得index位置对应的节点
next = header .next;
for (nextIndex =0; nextIndex<index; nextIndex++)
next = next .next;
} else {
next = header ;
for (nextIndex =size; nextIndex>index; nextIndex --)
next = next .previous;
}
}
public boolean hasNext() {
// 根据下一个节点index是否等于size,判断是否有下一个节点
return nextIndex != size;
}
public E next() {
checkForComodification();
// 遍历完成
if (nextIndex == size)
throw new NoSuchElementException();
// 赋值最近一次返回的节点
lastReturned = next ;
// 赋值下一次要返回的节点(next后移)
next = next .next;
// 将要返回的节点index索引+1
nextIndex++;
return lastReturned .element;
}
public boolean hasPrevious() {
return nextIndex != 0;
}
// 返回上一个节点(双向循环链表嘛、可以两个方向遍历)
public E previous() {
if (nextIndex == 0)
throw new NoSuchElementException();
lastReturned = next = next. previous;
nextIndex--;
checkForComodification();
return lastReturned .element;
}
public int nextIndex() {
return nextIndex ;
}
public int previousIndex() {
return nextIndex -1;
}
public void remove() {
checkForComodification();
// 取出当前返回节点的下一个节点
Entry<E> lastNext = lastReturned.next ;
try {
LinkedList. this.remove(lastReturned );
} catch (NoSuchElementException e) {
throw new IllegalStateException();
}
// 确认下次要返回的节点不是当前节点,如果是则修正
if (next ==lastReturned)
next = lastNext;
else
// 由于删除了一个节点,下次要返回的节点索引-1
nextIndex--;
// 重置lastReturned为header节点
lastReturned = header ;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == header)
throw new IllegalStateException();
checkForComodification();
lastReturned.element = e;
}
public void add(E e) {
checkForComodification();
lastReturned = header ;
addBefore(e, next);
nextIndex++;
expectedModCount++;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
介绍完毕,希望国际站疫情也到此为止。