五、Collection 接口 与 Iterator 接口

目录

1.Collecion 接口

2.Itertor 迭代器接口

3.增强for循环


1.Collecion 接口

Collection 接口是 List、Set 和 Queue 接口的父接口,通常情况下不被直接使用。Collection 接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作。定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。由于 Collection 是一个接口,因此这些方法必须由具体的子类去实现。

                     方法名称                                                                    说明
boolean add(E e)向集合中添加一个元素,如果集合对象被添加操作改变了,则返回 true
boolean addAll(Collection c)向集合中添加集合 c 中的所有元素,如果集合对象被添加操作改变了,则返回 true
void clear()清除集合中的所有元素,将集合长度变为 0
boolean contains(Object o)判断集合中是否存在指定元素
boolean containsAll(Collection c)判断集合中是否包含集合 c 中的所有元素
boolean isEmpty()判断集合是否为空
Iterator<E>iterator()返回一个 Iterator 对象,用于遍历集合中的元素。该方法继承自 Iterable,所有继承该接口的接口都是可迭代的。
boolean remove(Object o)从集合中删除一个指定元素,当集合中包含了一个或多个元素 o 时,该方法只删除第一个符合条件的元素,该方法将返回 true
boolean removeAll(Collection c)从集合中删除所有在集合 c 中出现的元素(相当于把调用该方法的集合减去集合 c)。如果该操作改变了调用该方法的集合,则该方法返回 true
boolean retainAll(Collection c)从集合中删除集合 c 里不包含的元素(相当于把调用该方法的集合变成该集合和集合 c 的交集),如果该操作改变了调用该方法的集合,则该方法返回 true
int size()返回集合中元素的个数
Object[] toArray()把集合转换为一个数组,所有的集合元素变成对应的数组元素

2.Itertor 迭代器接口

Iterator接口提供了以下三个方法:

                     方法名称                                                                    说明
boolean hasNext()如果被迭代的集合元素还没有被遍历完,则返回 true
Object next()返回集合里的下一个元素
void remove()删除集合里上一次 next 方法返回的元素

我们先来看看 Collection 的父接口 Iterable 接口,该接口只提供了一个方法 iterator ( ) ,所有 Collection 的实现类都实现了该方法,因此所有 Collection 的实现类都可以通过该方法来返回一个迭代器对象 Iterator。

可是我们也知道,每种类型集合实现方式都不尽相同,那么这些不同的集合如何返回一个相同结构的迭代器对象呢?我们先来看一看 ArrayList 集合关于迭代器的源码部分:

    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.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();
            }
        }

可以看到,在 ArrayList 中有一个内部类实现了 Iterator 接口,并重写了它的所有方法,而 iterator ( ) 方法返回的正是这个内部实现类的对象。其中的 cursor 指针记录了下一个要返回元素的位置,lastRet 指针记录了上一个已经返回的元素的位置。

在调用 next ( ) 方法时,首先会拿到 ArrayList 里的数组,然后 cursor 和 lastRet 指针后移一个元素位置,最后返回 lastRet 指针指向的元素;而 remove ( ) 方法则是直接调用了 ArrayList 的 remove ( ) 方法删除了lastRet指针指向的元素并重新规定两个指针的位置。

再来看看 LinkedList 关于迭代器的一部分源码:同样也是用了指针,只是迭代器方法的实现稍有不同。

private class Itr implements Iterator<E> {
       
        int cursor = 0;
        int lastRet = -1;
        int expectedModCount = modCount;

        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();
            }
        }
    }

知道了迭代器是如何实现的,但对于一个集合如 ArrayList 同样可以用 for 循环来遍历。那么为什么要使用迭代器呢,它的好处究竟在哪里?

其实在前面的文章中也提到过,有一部分集合是没有索引的,比如 Set 接口的实现类,此时就无法再通过 for 循环来遍历这些集合。而 Iterator 恰好提供了一种统一的遍历方式,可以允许对不同类型的集合使用相同的方式遍历,即所谓的迭代。只要此种集合实现了 iterator ( ) 方法,能够生成迭代器对象,就能用 Iterator 对它进行迭代。

下面以 HashSet 集合为例对此集合进行迭代操作:

    public static void main(String[] args) {
        Set<Integer> set = new HashSet();
        set.add(111);
        set.add(222);
        set.add(333);
        set.add(444);

        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            Object o = iterator.next();
            System.out.println(o);
        }
    }

    结果为:

    444
    333
    222
    111

3.增强for循环

在 JDK 1.5 中推出了一个高级的 for 循环,称之为增强 for 循环。增强 for 循环的底层实现也是一个迭代器,但是由于并没有为其提供与 remove ( ) 类似的方法,因此不能够做增删操作,否则会因为指针位置而报错。下面是增强 for 循环的使用案例:

    public static void main(String[] args) {
        List<Integer> set = new ArrayList<>();
        set.add(111);
        set.add(222);
        set.add(333);
        set.add(444);

        for(Integer temp:set){
            System.out.println(temp);
        }
    }

    结果为:

    111
    222
    333
    444

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值