赞
踩
Iterable
接口是什么?首先关注下图,这是Java集合架构层级,我们能发现其中Iterable
接口是中最顶端的那一个。
打开Collection
接口源码,能够看到Collection
接口是继承了Iterable
接口。
public interface Collection<E> extends Iterable<E> {
/**
* ......
*/
}
以下是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); } }
划重点:实现这个接口 允许一个对象成为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() );
}
2、获取Iterable
实现类对象的迭代器(Iterator)
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
String element = iterator.next();
System.out.println( element );
}
3、调用Iterable
的forEach()
方法
list.forEach( (element) -> {
System.out.println( element );
});
注: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()); } }
注意:同样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()); } }
Iterable
Iterator
两兄弟的区别Iterable接口是为了达到实现该接口的类,可以使用foreach循环的目的。
Iterator接口是基于迭代器模式,实现了对聚合类的存储和遍历的分离。
两者所强调的内容不同:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。