Iterable接口: (java.lang.Iterable) 是Java集合的顶级接口之一。
Collection接口继承Iterable,所以Collection的所有子类也实现了Iterable接口。
public interface Iterable<T> {
// 返回一个迭代器
Iterator<T> iterator();
// jdk1.8新加入的方法,遍历
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
// jdk1.8新加入的方法
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
default:是在java8中引入的关键字,可以在接口中定义方法体。
主要作用:使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。
测试:
@Test
public void testForEach() {
List<String> list = Arrays.asList("a","b","c","d","e");
list.forEach(str -> System.out.println(str);
}
public interface Enumeration<E> {
// 是否还有元素。
boolean hasMoreElements();
// 获取Enumeration
E nextElement();
}
Enumeration接口早在 JDK1.0 时就推出了,
当时比较早的容器比如 Hashtable, Vector 都使用它作为遍历工具。
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
// 获取迭代器
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
private <T> Enumeration<T> getEnumeration(int type) {
if (count == 0) {
return Collections.emptyEnumeration();
} else {
return new Enumerator<>(type, false);
}
}
}
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
// 获取迭代器
public Enumeration<E> elements() {
return new Enumeration<E>() {
int count = 0;
public boolean hasMoreElements() {
return count < elementCount;
}
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return elementData(count++);
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}
}
测试:
@Test
public void testIterator() {
Hashtable<String, String> hash = new Hashtable<>();
Enumeration<String> hashtableElements = hash.elements();
while (hashtableElements.hasMoreElements()) {
System.out.println(hashtableElements.nextElement());
}
Vector<String> vector = new Vector<>();
Enumeration<String> vectorElements = vector.elements();
while (vectorElements.hasMoreElements()) {
System.out.println(vectorElements.nextElement());
}
}
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator(),要求容器返回一个Iterator。
第一次调用Iterator的next()方法时,它返回序列的第一个元素。
注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,
为List设计的ListIterator具有更多的功能,可以从两个方向遍历List,也可以从List中插入删除元素。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
测试:
@Test
public void testIterator() {
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
ListIterator
游标( cursor ):在元素之间移动,若集合长度为N,那么游标位置就是N+1。
游标总存在元素中间: ↑ a ↑ b ↑。初始时游标为0,遍历结束时游标为2。
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
// 返回游标后的值,且游标++。
E next();
// 判断游标前面是否有元素;
boolean hasPrevious();
// 返回游标前面的元素,同时游标前移一位。
// 游标前没有元素就报 java.util.NoSuchElementException 的错。
// 所以使用前最好判断一下。
E previous();
// 返回游标后边元素的索引位置,初始为 0;
int nextIndex();
// 返回游标前面元素的位置,初始时为-1。
int previousIndex();
// 删除迭代器最后一次操作的元素。
// 当没有迭代,也就是没有调用next()或者previous()直接调用remove时会报java.lang.IllegalStateException错。
void remove();
// 更新迭代器最后一次操作的元素为E,也就是更新最后一次调用next()或者previous()返回的元素。
// 当没有迭代,也就是没有调用next()或者previous()直接调用set时会报java.lang.IllegalStateException错。
void set(E e);
// 在游标前面插入一个元素
void add(E e);
}
ListIterator接口的在ArrayList中具体实现。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
// 返回指定游标位置的迭代器
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
// 返回游标位置为0的迭代器
public ListIterator<E> listIterator() {
return new ListItr(0);
}
private class Itr implements Iterator<E> {
// 在获取迭代器时指定游标的值,默认为0。
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
// 返回游标后面的元素,且游标++
cursor = i + 1;
return (E) elementData[lastRet = i];
}
// 删除迭代器最后一次操作的元素。lastRet:index of last element returned; -1 if no such
// 当没有迭代,也就是没有调用next()或者previous()直接调用remove时会报java.lang.IllegalStateException错。
// 因为lastRet默认为-1,当调用next()后lastRet = i。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
// 返回游标前面的元素,且游标--
cursor = i;
return (E) elementData[lastRet = i];
}
// 设置迭代器最后一次操作的元素。lastRet:index of last element returned; -1 if no such
// 当没有迭代,也就是没有调用next()或者previous()直接调用set时会报java.lang.IllegalStateException错。
// 因为lastRet默认为-1,当调用next()后lastRet = i。
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 在游标的前面添加元素
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
}
(1)ListIterator有add()方法,可以向List中添加对象,Iterator不可以。
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。
但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历,Iterator不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现,Iterator不可以。
(4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。