当前位置:   article > 正文

Java集合系列 Iterable、Iterator这俩兄弟细致解读(超通俗易懂)_java iterable

java iterable

一、Iterable接口是什么?

首先关注下图,这是Java集合架构层级,我们能发现其中Iterable接口是中最顶端的那一个。
在这里插入图片描述

打开Collection接口源码,能够看到Collection接口是继承了Iterable接口。

public interface Collection<E> extends Iterable<E> {
    /**
     * ......
     */
}
  • 1
  • 2
  • 3
  • 4
  • 5

以下是Iterable接口源码及注释

/**
 * Implementing this interface allows an object to be the target of the "for-each loop" statement.
 * 实现这个接口允许一个对象成为for-each循环语句的目标
 */
public interface Iterable<T> {
	// 返回一个内部元素为T类型的迭代器(JDK1.5只有这个接口)
	Iterator<T> iterator();
	
	// 遍历内部元素,action意思为动作,指可以对每个元素进行操作(JDK1.8添加)
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
	
	// 创建并返回一个可分割迭代器(JDK1.8添加),分割的迭代器主要是提供可以并行遍历元素的迭代器,可以适应现在cpu多核的能力,加快速度。
	//(划重点:并行遍历元素 并行!)
	default Spliterator<T> spliterator() {
	    return Spliterators.spliteratorUnknownSize(iterator(), 0);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

划重点:实现这个接口 允许一个对象成为for-each循环语句的目标(大白话:实现此接口,能用foreach语句循环遍历)

Iterable接口定义了三个方法,其中两个提供了默认实现,只有iterator()是要求实现类必须实现的方法。
那么当某个类实现了Iterable接口就可以使用foreach进行迭代。同时Iterable中又封装了Iterator接口,那么这个类也可以使用Iterator迭代器
因而有三种方式可以迭代Iterable实现类的对象:
1、for-each循环

List<String> list = new ArrayList><();
list.add("AAA");
list.add("BBB");
list.add("CCC");
for( String element : list ){
    System.out.println( element.toString() );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、获取Iterable实现类对象的迭代器(Iterator

Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    String element = iterator.next();
    System.out.println( element );
}
  • 1
  • 2
  • 3
  • 4
  • 5

3、调用IterableforEach()方法

list.forEach( (element) -> {
    System.out.println( element );
});
  • 1
  • 2
  • 3

注:default修饰符,这也是Java8后新出现的。当给一个接口新添加一个方法,那么所有他的具体子类都必须实现此方法。为了能给接口拓展新功能,而又不必每个子类都要实现此方法,因此Java8新加了default关键字,被其修饰的方法可以不必由子类实现,并且由dafault修饰的方法在接口中有方法体,这打破了Java之前对接口方法的规范。

个人拙见:我们并不用过分在意这些方法的含义是什么,重点是需要记清楚,只要是实现了Iterable接口的对象,就都可以使用以上三种方式进行循环遍历

二、Iterator又是什么?

虽然在架构层级中并未包含,Iterator接口(迭代器)也是集合大家庭中的一员。Iterator主要是为了方便遍历集合中的所有元素(相当于是定义了遍历元素的范式)。

public interface Iterator<E> {
	// 是否有下一个元素
	boolean hasNext(); 
	
	// 获取下一个元素
	E next();   
	
	// 移除元素
	default void remove() {
		throw new UnsupportedOperationException("remove");
	}
	    
	// 对剩下的所有元素进行处理,action则为处理的动作,意为要怎么处理
	default void forEachRemaining(Consumer<? super E> action) {
		Objects.requireNonNull(action);
		while (hasNext())
	    action.accept(next());
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意:同样Iterator也是一个接口,目的是在于把不同集合的遍历方式抽象出来,这样我们使用迭代器遍历的时候,就不需要关注于集合内部结构,能够使用Iterator的内部方法直接遍历(也就是说,不管是针对List还是Set的遍历,我们都能够直接使用Iterator遍历拿到集合元素,而不需要关心是List还是Set)。那么这个时候,如果使用的数据结构有所变化,我们不需要去维护原有遍历集合的代码,因此也可以理解Iterator是有将集合与集合的遍历做了一个解耦

使用案例:

public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("张三1");
        list.add("张三2");
        list.add("张三3");
        list.add("张三4");
 
        List<String> linkList = new LinkedList<String>();
        linkList.add("link1");
        linkList.add("link2");
        linkList.add("link3");
        linkList.add("link4");
 
        Set<String> set = new HashSet<String>();
        set.add("set1");
        set.add("set2");
        set.add("set3");
        set.add("set4");
    
        //1.使用迭代器遍历ArrayList集合
        Iterator<String> listIt = list.iterator();
        while(listIt.hasNext()){
            System.out.println(listIt.next());
        }
        //2.使用迭代器遍历Set集合
        Iterator<String> setIt = set.iterator();
        while(setIt.hasNext()){
            System.out.println(listIt.next());
        }
        //3.使用迭代器遍历LinkedList集合
        Iterator<String> linkIt = linkList.iterator();
        while(linkIt.hasNext()){
            System.out.println(listIt.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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

三、Iterable Iterator两兄弟的区别

Iterable接口是为了达到实现该接口的类,可以使用foreach循环的目的。
Iterator接口是基于迭代器模式,实现了对聚合类的存储和遍历的分离
两者所强调的内容不同:

  • Iterable接口强调的是实现Iterable接口可使用foreach语法遍历,也可以使用迭代器遍历。
  • Iterator接口强调其实现类可使用迭代器遍历
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/692420
推荐阅读
相关标签
  

闽ICP备14008679号