迭代器接口
类图
迭代器是一个接口, 首先看一下java对迭代器接口的描述信息,以及这个接口定义的基本规范
迭代器接口的描述, 基本规范
实现这个接口, 允许一个对象成为深度 for - each 的目标。并且能够使用泛型。
- iterator
- 返回一个迭代器
- forEach(Consumer<? super T> action)
- 对每一个元素演示提供的动作, 直到所有的元素全部通过或者有一个元素抛出异常, 除非实现类有其他的规定,迭代器将按照顺序执行,操作引发的异常被中继到调用方。
- default
- 在接口中可以使用default关键字来修饰一些默认实现的方法。
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
测试
public class test implements Iterable<Integer> {
@Override
public Iterator<Integer> iterator() {
return null;
}
@Override
public void forEach(Consumer<? super Integer> action) {
action.accept(3);
}
@Override
public Spliterator<Integer> spliterator() {
return null;
}
public static void main(String[] args) {
test test = new test();
test.forEach(System.out::println);
}
}
对迭代器简单探究
ArrayList
迭代器方式
Collection接口也是迭代器接口的子接口, 则其必须对迭代器接口中做出的规范进行实现,下面进行简单的探究, 在java的集合框架中, 会存在一个简单的三层模型, 分别是
- 最上层的接口
- 定义规范
- 中间层的抽象类
- 对一些特殊的规范做出统一(或者特殊)的实现
- 最下层的具体实现类
- 根据自己的特电重写实现类中的实现, 和最上层接口中定义的规则。
对于这三层,将通过ArrayList进行探究, 先看下类图
- ArrayList 继承 AbstractList
- AbstractList 继承 AbstractCollection
- AbstractList 实现 List 接口
- AbstractColleciont 实现 Collection
Collection 接口
我们先看下 Collection 接口中迭代器相关的。几乎没有对迭代器接口做出任何的改动, 最上层的接口用来定义规范!
Iterator<E> iterator();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
AbstractColleciont 实现类
AbstractColleciont 这给抽象类也只是对 Collection 中的一些普遍方法做出了一些实现,对于迭代器部分也是没做出修改。
List接口
此接口中又定义了一个ListIterator 的方法, 用作List集合的迭代!
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
AbstractList 实现类
在这个抽象类中终于看到了关于迭代器的部分!可以看到最上层的迭代器方法中返回了一个迭代器对象!按照内部类的方式进行返回, 来探究以下其中的方法实现!
- cursor
- 记录着我们通过迭代器返回了几个元素
- lastRet
- 记录这我们最后一个返回元素的位置
- expectedModCount
- 我们期望被修改的次数, 用来判断并发!
- public boolean hasNext()
- 和 cursor 以及 size() 方法一起来判断是否还有下一个元素
- public E next()
- 返回下一个元素
- public void remove()
- 删除最近遍历的元素
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
arrayList 类
方法实现上基本和AbstractList 类似, 只不过多了具体 forEachRemaining(Consumer<? super E> consumer) 的实现, 以及forEach的重写(重写的是迭代器接口中默认的实现)
- forEach
- 其中遍历集合中的每一个元素, 对其进行我们的action!
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
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];
}
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();
}
}
List类
- 迭代器遍历
- for 循环遍历
- forEach遍历
public static void main(String[] args) {
Integer[] ints = {1, 2, 3, 4};
ArrayList<Integer> integers = new ArrayList<Integer>(Arrays.asList(ints));
Iterator<Integer> iterator = integers.iterator();
iterator.next();
iterator.remove();
while (iterator.hasNext()) {
System.out.println("while");
System.out.println("->" + iterator.next());
}
integers.forEach(System.out::println);
for (int i = 0; i < integers.size(); i++) {
System.out.println(integers.get(i));
}
}
Set类
- set.iterator();
- set.toArray();
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
set.add(2);
set.add(3);
set.add(4);
set.add(5);
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
for (Integer integer : set) {
System.out.println(integer);
}
Object[] toArray = set.toArray();
for (Object o : toArray) {
System.out.println(o);
}
}
Map类
- map.keySet();
- map.values();
- map.entrySet();
public static void main(String[] args) {
HashMap<String, Object> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
System.out.println(entry.getKey() + "- >" + entry.getValue());
}
Set<String> strings = map.keySet();
for (String string : strings) {
System.out.println(string);
}
Collection<Object> values = map.values();
for (Object value : values) {
System.out.println(value);
}
}