阳江营销网站开发,呼和浩特市网站,济南建设银行网点,有源码做网站1迭代器模式 迭代器是一种设计模式#xff0c;这种模式用于顺序访问集合对象的元素#xff0c;不需要知道集合对象的底层表示。 一般实现方式如下#xff1a;#xff08;来自#xff09; public interface Iterator {public boolean hasNext();public Object next();
} pu…1迭代器模式 迭代器是一种设计模式这种模式用于顺序访问集合对象的元素不需要知道集合对象的底层表示。 一般实现方式如下来自 public interface Iterator {public boolean hasNext();public Object next();
} public interface Container {public Iterator getIterator();
} public class NameRepository implements Container {public String names[] {Robert , John ,Julie , Lora};Overridepublic Iterator getIterator() {return new NameIterator();}private class NameIterator implements Iterator {int index;Overridepublic boolean hasNext() {if(index names.length){return true;}return false;}Overridepublic Object next() {if(this.hasNext()){return names[index];}return null;} }
} public class IteratorPatternDemo {public static void main(String[] args) {NameRepository namesRepository new NameRepository();for(Iterator iter namesRepository.getIterator(); iter.hasNext();){String name (String)iter.next();System.out.println(Name : name);} }
} 一般情况我们自己开发时很少自定义迭代器因为java本身已经把迭代器做到内部中了 2Java中的迭代器 1Iterator接口 package java.util;import java.util.function.Consumer;public interface IteratorE {/** * 如果迭代器又更多的元素返回true。* 换句话说如果next方法返回一个元素而不是抛出一个异常则返回true。 */ boolean hasNext();//返回迭代器中的下一个元素如果没有则抛出NoSuchElementException异常E next();/** * 从底层集合中删除该迭代器返回的最后一个元素可选操作。每执行一次next方法这个方法只能被调用1次。* 如果在迭代过程中除了调用此方法之外任何其他方法修改基础集合则迭代器的行为是不确定的。 * 默认实现是抛出一个UnsupportedOperationException异常不执行其他操作。 * 如果每次调用该方法前next方法没有执行则抛出IllegalStateException异常。 */default void remove() {throw new UnsupportedOperationException(remove);}/** * since 1.8函数编程。 * 对每个剩余元素执行给定的操作直到所有元素都被处理或动作抛出异常为止。 * 如果指定了该顺序则按迭代顺序执行操作。动作抛出的异常被传递给调用者。 * 如果action为null则抛出NullPointerException */default void forEachRemaining(Consumer? super E action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}
} 首先Iterator接口是属于java.util包的。然后里面只有4个方法用法介绍请看注释。 forEachRemaining方法是Java8函数编程新加入的。作用是对前游标之后的每个元素进行处理没有返回值具体怎么处理根据传入的函数。这项里操作使得迭代器更加灵活操作粒度更加细致。 补充default关键字可以让接口中的方法可以有默认的函数体当一个类实现这个接口时可以不用去实现这个方法当然这个类若实现这个方法就等于子类覆盖了这个方法最终运行结果符合Java多态特性。Java8的新特性 类注释 /*** An iterator over a collection. {code Iterator} takes the place of {link Enumeration} in the Java Collections Framework. Iterators* differ from enumerations in two ways:** ul* li Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.* li Method names have been improved.* /ul** pThis interface is a member of the a href{docRoot}/../technotes/guides/collections/index.htmlJava Collections Framework/a.*/ Iterator是集合上的迭代器。在Java集合框架中Iterator用来替代EnumerationIterator与Enumeration有以下两点区别 Iterator允许调用者通过定于语义良好的迭代器删除底层集合中的元素。方法名称已得到改进。这个接口是Java集合框架的成员。除了如上两点不同外Java8版本Iterator还加入了函数式编程。 2Iterable接口 package java.lang;// 实现此接口允许对象成为“for-each loop”语句的目标。
public interface IterableT { // 返回类型为 T元素的迭代器。IteratorT iterator();/*** since 1.8 * 对Iterable的每个元素执行给定的操作直到所有元素都被处理或动作引发异常。 * 除非实现类另有规定否则按照迭代的顺序执行操作如果指定了迭代顺序。 动作抛出的异常被转发给调用者。 * 抛出NullPointerException - 如果指定的动作为空*/default void forEach(Consumer? super T action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}/*** since 1.8 * 在Iterable描述的元素上创建一个Spliterator。Spliterator继承了迭代器的fail-fast属性。 * */default SpliteratorT spliterator() {return Spliterators.spliteratorUnknownSize(iterator(), 0);}
} Java集合包最常用的有Collection和Map两个接口的实现类。Map的实现类迭代器是内部实现的而Collection继承了Iterable接口。 这里以ArrayList为例梳理一下Iterator的工作流程。 ArrayList是Collection的子类而Collection又实现了Iterable接口Iterable接口里面有iterator()方法该方法返回一个迭代器对象。所以ArrayList或其父类也必须实现iterator()方法。 iterator()方法返回一个Iterator对象而前文中Iterator是个接口。我们不能不知道具体用哪个实现类也不能直接new接口所以我们找到其直接父类AbstractList查看iterator()到底如何实现的 public IteratorE iterator() {return new Itr();}private class Itr implements IteratorE {// Index of element to be returned by subsequent call to next.int cursor 0;/*** Index of element returned by most recent call to next or* previous. Reset to -1 if this element is deleted by a call* to remove.*/int lastRet -1;/*** The modCount value that the iterator believes that the backing* List should have. If this expectation is violated, the iterator* has detected concurrent modification.*/int expectedModCount modCount;public boolean hasNext() {return cursor ! size();}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();}}public void remove() {if (lastRet 0)throw new IllegalStateException();checkForComodification();try {AbstractList.this.remove(lastRet);if (lastRet cursor)cursor--;lastRet -1;expectedModCount modCount;} catch (IndexOutOfBoundsException e) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (modCount ! expectedModCount)throw new ConcurrentModificationException();}} 这里是通过内部类实现了Iterator接口然后再将其实例对象返回。 原理很简单每调用一次next方法先返回当前游标指向位置的值然后游标往下移动一位直到游标数值等于list的size。 而在ArrayList类里面又提供了一个实现版本 /*** An optimized version of AbstractList.Itr*/private class Itr implements IteratorE {int cursor; // index of next element to returnint lastRet -1; // index of last element returned; -1 if no suchint 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();}}OverrideSuppressWarnings(unchecked)public void forEachRemaining(Consumer? super E consumer) {Objects.requireNonNull(consumer);final int size ArrayList.this.size;int i cursor;if (i size) {return;}final Object[] elementData ArrayList.this.elementData;if (i elementData.length) {throw new ConcurrentModificationException();}while (i ! size modCount expectedModCount) {consumer.accept((E) elementData[i]);}// update once at end of iteration to reduce heap write trafficcursor i;lastRet i - 1;checkForComodification();}final void checkForComodification() {if (modCount ! expectedModCount)throw new ConcurrentModificationException();}} next方法很好理解和父类大概是一个意思。remove方法是调用ArrayList.this.remove(lastRet)实现 public E remove(int index) {rangeCheck(index);modCount;E oldValue elementData(index);int numMoved size - index - 1;if (numMoved 0)System.arraycopy(elementData, index1, elementData, index,numMoved);elementData[--size] null; // clear to let GC do its workreturn oldValue;} numMoved 是计算要移动的元素个数删除数组的某一位置的值后面的值要依次往前移。 cursor lastRet; lastRet -1; 表示删除之后游标前移1位。为什么这么做举个例子数组a [1234]若cursor 2游标指向数字3则lastRet 1。当删除a[1]的时候a [134]。3对应的位置变为1了所以会有cursor lastRet。 lastRet的值置为-1这里很好的解释了前面注释中为什么remove方法一定要在next方法之后执行了。 转载于:https://www.cnblogs.com/ouym/p/8857448.html