当前位置:   article > 正文

Java的集合框架(Collection Framework)中的Iterator接口详解

Java的集合框架(Collection Framework)中的Iterator接口详解


在Java的集合框架(Collection Framework)中, Iterator接口提供了一种遍历集合元素的方法。它允许程序员以统一的方式遍历不同类型的集合,如 ArrayListHashSetLinkedList等。

Iterator接口

Iterator接口定义了三个主要的方法:

  1. boolean hasNext()

    • 如果集合中还有剩余元素可以迭代,返回true;否则返回false
  2. E next()

    • 返回迭代中的下一个元素。如果没有更多元素,则抛出NoSuchElementException
  3. void remove()

    • 移除调用next()方法时返回的最后一个元素。每次调用next()方法后只能调用一次remove()方法,否则会抛出IllegalStateException。此方法是可选的,具体实现可以选择是否支持此操作。

Iterator的实现原理

不同的集合类提供了自己的Iterator实现,它们通过内部类来实现Iterator接口,以适应不同的集合结构。下面以ArrayListHashSet为例,解释它们的Iterator实现。

ArrayListIterator实现

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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

HashSetIterator实现

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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

使用Iterator遍历集合

以下是使用Iterator遍历ArrayListHashSet的示例:

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());
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

Iterator定义为接口的原因

在Java中,将Iterator定义为接口是一种设计上的选择,目的是提供一个统一的迭代机制,使不同类型的集合都能以一致的方式进行遍历。以下是将Iterator定义为接口的主要原因:

1. 接口提供了一致的API

通过定义一个接口,Java标准库能够为所有的集合类型提供一致的API来遍历元素。这意味着你可以用相同的方法遍历ArrayListHashSetLinkedList等各种集合,而不需要知道这些集合的内部实现细节。

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());
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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();
}
  • 1
  • 2
  • 3
  • 4
  • 5

例子: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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

例子: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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

总结

Iterator定义为接口的主要目的是提供一个统一、灵活且可扩展的迭代机制。通过这种方式,Java集合框架能够支持多种类型的集合,并且客户端代码能够以一致的方式使用这些集合。这种设计不仅简化了集合的使用,还提高了代码的可维护性和可扩展性。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号