Iterator和Iterable解析

时间:2019-10-10 12:03来源:编程技术
事先一贯搞不清楚Iterator和Iterable到底有怎么着关系,它们的不一样是怎么着,明天查看Java集结类源码才发现里面包车型地铁名堂,接下去给我们讲讲小编的解析与领会。 迭代器是一种

事先一贯搞不清楚Iterator和Iterable到底有怎么着关系,它们的不一样是怎么着,明天查看Java集结类源码才发现里面包车型地铁名堂,接下去给我们讲讲小编的解析与领会。

迭代器是一种情势,它可以使得对于种类类型的数据结构的遍历行为与被遍历的目标分别,即大家没有必要关怀该连串的底层结构是怎么着体统的。只要得到这几个指标,使用迭代器就能够遍历那么些指标的内部.

Iterable是接口,Iterable是1.5引进的新特色,Iterator是1.2就有了,二者皆感觉着迭代制作,Iterable只是包装了Iterator,进而允许完成此接口的目的变成foreach语句的靶子,并且那样的话,更利于现在的增加。

1.Iterator

public interface Iterable<T> { /** * Returns an iterator over elements of type {@code T}. * * @return an Iterator. */ Iterator<T> iterator(); default void forEach(Consumer<? super T> action) { Objects.requireNonNull; for (T t : this) { action.accept; } } default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator; }}

    Java提供三个特意的迭代器Iterator,大家能够对某些系列落成该interface,来提供标准的Java迭代器。Iterator接口兑现后的成效是“使用”多个迭代器.

Java集结Collection接口就扩充了Iterable接口。完成Iterable接口的那个类就足以具有加强的for循环,该循环施于那么些类以上以观察他们全部的项。

文书档案解释:

public interface Collection<E> extends Iterable<E> { int size(); boolean isEmpty(); boolean contains; Iterator<E> iterator(); Object[] toArray(); boolean add; boolean remove; boolean containsAll(Collection<?> c); boolean removeAll(Collection<?> c); default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull; boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext { if (filter.test(each.next { each.remove(); removed = true; } } return removed; } boolean retainAll(Collection<?> c); void clear(); boolean equals; int hashCode(); @Override default Spliterator<E> spliterator() { return Spliterators.spliterator; } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator; }}

java.util  Interface Iterator<E>

All Known Subinterfaces:
ListIterator<E>, XMLEventReader

All Known Implementing Classes:
BeanContextSupport.BCSIterator, EventReaderDelegate, Scanner

 

public interface Iterator<E>

An iterator over a collection. Iterator takes the place of Enumeration in the Java collections framework. Iterators differ from enumerations in two ways:

  • Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
  • Method names have been improved.

This interface is a member of the Java Collections Framework.

 

Package  java.util; 

public   interface Iterator { 
    boolean  hasNext(); //判断是否存在下一个对象元素 
    E  next(); 
    void  remove(); 
}

2.Iterable

Java中还提供了三个Iterable接口,Iterable接口贯彻后的功效是“再次回到”一个迭代器,大家常用的落到实处了该接口的子接口有: Collection, Deque, List, Queue, Set 等.该接口的iterator()方法再次来到二个正规的Iterator达成。达成那么些接口允许对象形成Foreach 语句的靶子。就足以因此Foreach语法遍历你的平底系列。 Iterable接口富含三个力所能致发生Iterator的iterator()方法,並且Iterable接口被foreach用来在体系中活动。由此只要成立了别的完成Iterable接口的类,都能够将它用来foreach语句中。

看一下文档的分解

public interface Iterable<T>

Implementing this interface allows an object to be the target of the "foreach" statement.

应用Iterator的简练例子 

import java.util.*; 

public class TestIterator { 
    public static void main(String[] args) { 

    List list=new ArrayList(); 

    Map map=new HashMap(); 

    for(int i=0;i<10;i++){ 

        list.add(new String("list"+i) ); 
        map.put(i, new String("map"+i)); 

    }   

    Iterator iterList= list.iterator();//List接口实现了Iterable接口 
    while(iterList.hasNext()){ 

    String strList=(String)iterList.next(); 

    System.out.println(strList.toString()); 

    } 

    Iterator iterMap=map.entrySet().iterator(); 

    while(iterMap.hasNext()){ 

        Map.Entry strMap=(Map.Entry)iterMap.next(); 

        System.out.println(strMap.getValue()); 
        } 

    } 
} 

接口Iterator在不相同的子接口中会依照气象打开职能的扩张,举个例子针对List的迭代器ListIterator,该迭代器只好用于各个List类的访谈。

ListIterator能够双向移动。增多了 previous()等方法.

上边的事例使用泛型和forEach的写法:

import java.util.*; 
public class TestIterator { 

    public static void main(String[] args) { 

        List<String> list=new ArrayList<String> (); 

        for(int i=0;i<10;i++){ 

            list.add(new String("list"+i) ); 

        } 

    for(String str:list){ 

        System.out.println(str); 
        } 
} 

能够看看,使用for each循环语句的优势在于尤其简明,更不便于出错,不必关注下标的最初值和结束值。

forEach不是关键字,关键字依然for,语句是由iterator达成的,他们最大的差异之处就在于remove()方法上。 平日调用删除和丰盛方法都以实际集结的不二等秘书诀,比如: List list = new ArrayList(); list.add(...); list.remove(...); 可是,借使在循环的进度中调用集结的remove()方法,就能够促成循环出错,因为循环进度中list.size()的轻重变化了,就导致了错误。 所以,假诺想在循环语句中删除集结中的有些成分,将在用迭代器iterator的remove()方法,因为它的remove()方法不但会去除成分,还或者会维护一个标志,用来记录前段时间是还是不是可去除状态,举例,你不能够三番一次四遍调用它的remove()方法,调用从前起码有三遍next()方法的调用。 forEach正是为了让用iterator循环访问的方式简单,写起来更有益。当然效率不太全,所以但如有删除操作,依旧要用它原来的款型。

 

4 使用for循环与使用迭代器iterator的对峙统一

频率上的各有有事

利用ArrayList对轻巧访谈相当的慢,而for循环中的get()方法,采取的正是随机拜见的点子,因而在ArrayList里,for循环一点也不慢

接纳LinkedList则是逐个访谈不慢,iterator中的next()方法,采纳的便是顺序访谈的不二等秘书籍,因而在LinkedList里,使用iterator很快

从数据结构角度分析,for循环切合访谈顺序结构,可以依靠下标火速获得钦点成分.而Iterator 符合访谈链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问尚未种种的集结. 而采纳 Iterator 的实惠在于能够动用一样方式去遍历集结相月素,而毫不思虑集合类的当中贯彻(只要它达成了 java.lang.Iterable 接口),即使选择 Iterator 来遍历集合桐月素,一旦不再行使 List 转而采取 Set 来协会数量,那遍历成分的代码不用做任何改动,倘若选取 for 来遍历,那具备遍历此汇集的算法都得做相应调解,因为List有序,Set严节,结构不一致,他们的拜见算法也不一样样.

兑现Iterable接口的汇集必得提供二个叫作itrator的秘诀,该措施又赶回多个Iterator类型的靶子。所以举例List集结类,Set类,他们达成了Collection接口,自然完毕了Iterable接口,在其源码中有实际的iterator方法,比如:ArraryList类中,它实现了List接口

 public Iterator<E> iterator() { return new 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; 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  elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove; cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } ...

Iterator接口的思路是,通过iterator方法,种种会集均可创立并赶回给客商三个落到实处Iterator接口的靶子。

public interface Iterator<E> { boolean hasNext(); T next(); void remove();}

Iterator平常用来轻便遍历集合中的成分。而Iterator还可能有三个立竿见影的艺术叫做remove()方法,相对于Collection中的remove来说,它装有越来越多的亮点。

对比Collection中remove方法和Iterator中remove方法

  • 抽象类AbstractCollection(实现了Collection接口)的remove方法
public boolean remove { Iterator<E> it = iterator(); if  { while (it.hasNext { if ==null) { it.remove(); return true; } } } else { while (it.hasNext { //找出要被删除的项 if (o.equals)) { it.remove(); return true; } } } return false; }

Collection的remove方法必须首先搜索要被去除的项,费用一点都不小。

  • Iterator中的remove方法
 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; public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove;//remove()方法下面有给出 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }

如上是ArrayList中其落到实处Iterator接口的里边类中remove方法,或然里面多少变量你看不懂,须求联系整个源码技术够知情它大致的情趣。

以下是ArrayList重写AbstractList中remove()方法。

public E remove(int index) { rangeCheck;//检查是否越界 modCount++; E oldValue = elementData;//得到要删除的元素 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);//复制数组 elementData[--size] = null; // clear to let GC do its work return oldValue;//返回要删除的元素 }

轻巧看出Iterator的remove方法并从未多少个二个相比找寻所要删除的项,而是了然要去除项的纯粹地点,那么删除它的支出就小非常多。

应用Iterator的基本准则

若果对正值被迭代的集结实行社团上的转移(即对聚焦使用add,remove或clear方法),那么迭代器就不再合法(何况在其后使用该迭代器时将会有ConcurrentModificationException非常被抛出)。然则,借使迭代器调用了它和睦的remove方法,那那几个迭代器照旧是官方的,所以那是我们一时候更愿意利用迭代器的remove方法的第三个原因。

编辑:编程技术 本文来源:Iterator和Iterable解析

关键词: