结合类的接口是Collection,这个接口有两个基本方法
public interface Collection<E>
{
boolean add(E element);
Iterator<E> iterator();
...
}
iterator方法返回一个实现了Iterator接口的对象。可以使用这个迭代器对象依次访问集合中的元素。
1、Iterable
Iterable英文意思为:可迭代的、迭代器、可遍历的.
Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素。Iterable 接口中定义了iterator方法,该方法会返回一个迭代器。Iterator 接口提供了遍历合集中元素的方法。
修饰符和返回值 | 方法名 | 描述 |
---|---|---|
Iterator | iterator() | 返回一个内部元素为T类型的迭代器 |
default void | forEach(Consumer<? super T> action) | 对内部元素进行遍历,并对元素进行指定的操作 |
default Spliterator | spliterator() | 创建并返回一个可分割迭代器 |
Iterator<Integer> iterator=list.iterator(); //获取ArrayList内部迭代器
while(iterator.hasNext()){ //hasNext()方法判断是否还有元素
System.out.println(iterator.next()); //next()返回当前元素,并且将指针移向下个元素
还可以使用"for-each loop"形式进行遍历,增强for形式在Java中只是一个语法,实际编译的时候,还是会转换为迭代器形式,
for (Integer integer : list) {
System.out.println(integer);
}
进行迭代遍历的时候我们需要注意在遍历的过程中,如果我们对元素进行添加删除,那么会造成并行修改异常(ConcurrentModificationException)!!
对于这种情况,我们应当使用迭代器Iterator内部的remove()方法,而不是使用集合list直接删除元素。
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i == 2) {
list.remove(i); /* 错误写法!*/
iterator.remove(); /* 正确做法! */
}
}
如果我们自己想自己写一个集合,实现Iterable接口,并可以使用"for-each loop"形式遍历,那么我们需要自己来重写一个迭代器(Iterator)并返回它。
public class MyCollection<E> implements Iterable<E> {
@Override
public Iterator iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<E>{
@Override
public boolean hasNext() {
return false;
}
@Override
public E next() {
return null;
}
}
}
2、迭代器 Iterator 接口
每种合集都是可迭代的(Iterable) 。可以获得集合的 Iterator
对象来遍历合集中的所有元素。Iterator 是一种经典的设计模式,用于在不需要暴露数据是如何保存在数据结构的细节的情况下,来遍历一个数据结构
。
Collection 接口继承自 Iterable 接口。
Iterable 接口中定义了iterator方法,该方法会返回一个迭代器。Iterator 接口提供了遍历合集中元素的方法。
iterator()方法返回一个Iterator 的实例。用next()方法提供对合集中元素的顺序访问.
Iterator接口包含3个方法:
public interface Iterator<E>
{
<E> next();
boolean hasNext();
void remove();
}
通过反复调用next()可以遍历集合中的每个元素,当所有元素都遍历了一遍之后,即到达了集合的末尾,next方法会抛出一个NoSuchElementException
错误。因此,我们在调用next前调用hasNext判断是否有下一个元素,如果有下一个元素返回true。
如果想要查看集合中的所有元素,就请求一个迭代器!
Collection<String> c = ...;
Iterator<String> iter = c.iterator();
whie(iter.hasNext())
{
String element = iter.next();
// do something with element
}
//while循环可以用for each代替
for (String element:c)
{
// do something with element
}
在JAVA中,查找一个元素的唯一方法是调用next,我们可以把JAVA的迭代器认为是位于两个元素之间。当调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
3、删除元素
Iterator接口定义了一个remove方法,删除上次调用next方法时返回的元素。所以remove方法和next方法是相互依赖的!如果调用remove前没有调用next方法,会引发IllegalStateException
错误。
Iterator<String> ite = c.itetator();
ite.next();
ite.remove(); // it's right!
4、并发修改
如果在某个迭代器修改集合时,另一个迭代器对其进行遍历,会出现混乱。如果一个迭代器发现它的集合被另一个迭代器修改了,或是被该集合自身的方法修改了,就会抛出一个 Concurrent ModifacationException
异常。
为了避免发生并发修改异常,规则:
根据需要给容器附加许多的迭代器,但这些迭代器只能读取列表。再单独附加一个既能读又能写的迭代器。
一个简单的方法:
集合可以跟踪改写操作(例如添加或删除)的次数。每个迭代器都维护一个独立的计数值。在每个迭代器方法的开始处检查自己改写操作的计数值是否与集合的改写操作的计数值一致。如果不一致,抛出一个 Concurrent ModifacationException
异常。
5、练习
举个例子如下:
for (Iterator<Hero> iterator = heros.iterator(); iterator.hasNext();) {
Hero hero = (Hero) iterator.next();
System.out.println(hero);
}
or
// 向后遍历
Iterator<Strting> iterator = list.iterator();
while(iteator.hasNext())
System.out.print(iterator.next().toUpperCase() + " ");
System.out.println();
//向前遍历
iterator= list.iterator(list. size());
while (iterator.hasPrevious()) {
System . out.print(iterator.previous() + " ") ;
}