文章目录
在Java的集合框架(Collection Framework)中,
Iterator
接口提供了一种遍历集合元素的方法。它允许程序员以统一的方式遍历不同类型的集合,如
ArrayList
、
HashSet
、
LinkedList
等。
Iterator
接口
Iterator
接口定义了三个主要的方法:
-
boolean hasNext()
:- 如果集合中还有剩余元素可以迭代,返回
true
;否则返回false
。
- 如果集合中还有剩余元素可以迭代,返回
-
E next()
:- 返回迭代中的下一个元素。如果没有更多元素,则抛出
NoSuchElementException
。
- 返回迭代中的下一个元素。如果没有更多元素,则抛出
-
void remove()
:- 移除调用
next()
方法时返回的最后一个元素。每次调用next()
方法后只能调用一次remove()
方法,否则会抛出IllegalStateException
。此方法是可选的,具体实现可以选择是否支持此操作。
- 移除调用
Iterator
的实现原理
不同的集合类提供了自己的Iterator
实现,它们通过内部类来实现Iterator
接口,以适应不同的集合结构。下面以ArrayList
和HashSet
为例,解释它们的Iterator
实现。
ArrayList
的Iterator
实现
ArrayList
是基于动态数组实现的,因此它的Iterator
实现非常简单,直接通过索引来访问数组元素。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 内部类实现了Iterator接口
private class Itr implements Iterator<E> {
int cursor; // 下一个元素的索引
int lastRet = -1; // 上一个返回的元素的索引
public boolean hasNext() {
return cursor != size();
}
public E next() {
int i = cursor;
if (i >= size())
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
}
}
// 返回一个新的Iterator实例
public Iterator<E> iterator() {
return new Itr();
}
}
HashSet
的Iterator
实现
HashSet
是基于HashMap
实现的,因此它的Iterator
是遍历HashMap
的键集合。
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable {
private transient HashMap<E,Object> map;
// 内部类实现了Iterator接口
private class HashIterator implements Iterator<E> {
private final Iterator<E> it;
HashIterator() {
it = map.keySet().iterator();
}
public boolean hasNext() {
return it.hasNext();
}
public E next() {
return it.next();
}
public void remove() {
it.remove();
}
}
// 返回一个新的Iterator实例
public Iterator<E> iterator() {
return new HashIterator();
}
}
使用Iterator
遍历集合
以下是使用Iterator
遍历ArrayList
和HashSet
的示例:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
// 使用Iterator遍历ArrayList
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
arrayList.add("C");
Iterator<String> arrayListIterator = arrayList.iterator();
while (arrayListIterator.hasNext()) {
System.out.println(arrayListIterator.next());
}
// 使用Iterator遍历HashSet
HashSet<String> hashSet = new HashSet<>();
hashSet.add("X");
hashSet.add("Y");
hashSet.add("Z");
Iterator<String> hashSetIterator = hashSet.iterator();
while (hashSetIterator.hasNext()) {
System.out.println(hashSetIterator.next());
}
}
}
将Iterator
定义为接口的原因
在Java中,将Iterator
定义为接口是一种设计上的选择,目的是提供一个统一的迭代机制,使不同类型的集合都能以一致的方式进行遍历。以下是将Iterator
定义为接口的主要原因:
1. 接口提供了一致的API
通过定义一个接口,Java标准库能够为所有的集合类型提供一致的API来遍历元素。这意味着你可以用相同的方法遍历ArrayList
、HashSet
、LinkedList
等各种集合,而不需要知道这些集合的内部实现细节。
import java.util.*;
public class IteratorExample {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
arrayList.add("C");
Set<String> hashSet = new HashSet<>();
hashSet.add("X");
hashSet.add("Y");
hashSet.add("Z");
printElements(arrayList);
printElements(hashSet);
}
public static void printElements(Collection<String> collection) {
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
2. 解耦集合的实现和使用
通过使用接口,Java的集合框架能够实现高内聚、低耦合的设计。集合的具体实现类负责提供具体的迭代逻辑,而客户端代码只需要依赖于Iterator
接口即可。
3. 灵活的多态性
接口允许多态性,这意味着你可以使用Iterator
接口来处理任何实现了该接口的对象。这种多态性使得代码更加灵活和可扩展。
4. 支持不同的迭代实现
不同的集合可能需要不同的迭代实现,例如ArrayList
需要基于索引的迭代,而LinkedList
需要基于节点的迭代。通过定义Iterator
接口,不同的集合可以提供自己的迭代器实现,以适应它们的内部结构。
5. 强制实现必要的方法
接口定义了一组必须实现的方法,如hasNext()
、next()
和remove()
,确保所有实现都提供这些基本的迭代功能。这种强制性保证了接口的一致性和可靠性。
例子:Iterator
接口定义
以下是Iterator
接口的定义:
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
例子:ArrayList
的迭代器实现
以下是ArrayList
中的迭代器实现:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private class Itr implements Iterator<E> {
int cursor; // 下一个元素的索引
int lastRet = -1; // 上一个返回的元素的索引
public boolean hasNext() {
return cursor != size();
}
public E next() {
int i = cursor;
if (i >= size())
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
}
}
public Iterator<E> iterator() {
return new Itr();
}
}
例子:HashSet
的迭代器实现
以下是HashSet
中的迭代器实现:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable {
private transient HashMap<E,Object> map;
private class HashIterator implements Iterator<E> {
private final Iterator<E> it;
HashIterator() {
it = map.keySet().iterator();
}
public boolean hasNext() {
return it.hasNext();
}
public E next() {
return it.next();
}
public void remove() {
it.remove();
}
}
public Iterator<E> iterator() {
return new HashIterator();
}
}
总结
将Iterator
定义为接口的主要目的是提供一个统一、灵活且可扩展的迭代机制。通过这种方式,Java集合框架能够支持多种类型的集合,并且客户端代码能够以一致的方式使用这些集合。这种设计不仅简化了集合的使用,还提高了代码的可维护性和可扩展性。