迭代器

迭代器是一种重要的设计模式,Java语言已经内置实现了。和迭代器相关的两个重要接口是Iterableiterator

集合类应该实现Iterable,它只有一个方法Iterator<T> iterator(),也就是返回一个实现了iterator的对象,这个对象就是真正的迭代器对象,我们使用它迭代我们的集合类。

迭代器接口Iterator有三个主要方法:

  • boolean hasNext() 返回迭代的下一个对象是否存在
  • E next() 返回迭代的下一个对象
  • void remove() 从集合中删除当前迭代的对象

使用迭代器遍历ArrayList

ArrayList实现了List接口,List继承了Collection接口,Collection接口继承了Iterable接口。因此我们可以使用迭代器遍历ArrayList

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main
{
    public static void main(String[] args)
    {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);

        Iterator<Integer> integerIterator = integerList.iterator();
        while(integerIterator.hasNext())
        {
            System.out.println(integerIterator.next());
        }
    }
}

更简洁的foreach语法

Java引入了foreach语法,简化了迭代器的使用。实际上,使用foreach也是迭代器在起作用。

使用foreach遍历ArrayList:

public class Main
{
    public static void main(String[] args)
    {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);

        for(Integer integer : integerList)
        {
            System.out.println(integer);
        }
    }
}

实现自己的可迭代类

有时我们需要让自己设计的类能够迭代,Java中我们不需要再“发明”一个迭代器模式,因为Java语言已经为我们提供了这样的两个接口。下面例子编写了一个我们自己的泛型可迭代对象,并使用foreach语法进行遍历:

MyCollection.java

import java.util.Iterator;

class MyCollection<T> implements Iterable<T>
{

    private T[] array;
    private int size;

    public MyCollection(T[] array)
    {
        this.array = array;
        this.size = array.length;
    }

    @Override
    public Iterator<T> iterator()
    {
        return new Iterator<T>()
        {

            private int index = 0;

            @Override
            public boolean hasNext()
            {
                return index < size;
            }

            @Override
            public T next()
            {
                return array[index++];
            }
        };
    }
}

Main.java

public class Main
{
    public static void main(String[] args)
    {
        Integer[] intArr = {1, 2, 3};
        MyCollection<Integer> intCollection = new MyCollection<>(intArr);

        for(Integer integer : intCollection)
        {
            System.out.println(integer);
        }
    }
}

MyCollection实现了Iterable接口,iterator()方法中,使用匿名类创建一个Iterator迭代器对象并返回。迭代器对象中包含了hasNext()next()的实现。由于我们的MyCollection实现了Iterable,因此Main中可以使用foreach对其进行迭代。

Java8对foreach的增强

Java8引入了lambda表达式,并向Iterable添加了一个方法void forEach(Consumer<? super T> action),这是一个函数式接口,我们可以创建匿名类实现Consumer,但这样写太繁琐了,下面演示结合lambda表达式的foreach简化写法:

public class Main
{
    public static void main(String[] args)
    {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);

        integerList.forEach((i)-> System.out.println(i));
    }
}

上面代码中,i是正在迭代的变量,我们省略了其类型,因为lambda表达式会进行类型推断。实际上,我们还能把上面的代码进一步简化成方法引用:integerList.forEach(System.out::println);,不过我一直不是很习惯这种写法,还是觉得上一种写法比较优美。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap