标签:Iterator 迭代 lastRet elementData cursor new 设计模式 throw
迭代器设计模式
用集合类实现Aggregate接口,并实现其iterator方法,生成特定的迭代器对象,但返回时返回为Iterator类型,以此来抽象编程,实现解耦合的目的。
类图:
当使用不同的集合实现类时,可以使用通用的代码,因为是面向接口编程,在循环中只使用了迭代器接口中的函数,达到了解耦的目的。
while(it.hasNext()){ Book book = (Book)it.next(); System.out.println(book.getName()); }
原则:不要只使用具体类来编程,要优先使用抽象类和接口来编程。
例子
这个例子与本设计模式没有太多关系,但是确实是迭代器相关的问题。
当需求是按要求删除集合内的元素时,如果简单使用for循环进行删除,删除一个元素时,会使集合长度改变,影响取到的下一个元素。
并且增强for循环不能对元素进行删除,因为增强for使用迭代器实现的,某些对集合造成修改的操作会使迭代器失效。
具体哪些操作会使迭代器失效需要继续学习。
解决方案:
1.反向遍历从后往前遍历,每次不管删不删反正index都会减一,避免了越过元素的问题。
2.使用迭代器,迭代器在实现的过程中,考虑了删除元素的可能性:
当next时,用cursor指向下一个元素,而lastRet指向当前元素
当删除一个元素时,会将cursor返回到前一个元素,并且将lastRet置为-1
以上是ArrayList中的内部类的实现方法,代码如下:
public Iterator<E> iterator() { return new Itr(); } /** * An optimized version of AbstractList.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; 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(); } } @Override @SuppressWarnings("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 traffic cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
其他集合实现方法应该类似。
3.使用流进行处理
list = list.stream().filter(u -> !"5".equals(u.getId()+"")).collect(Collectors.toList());
list.removeIf(u->"5".equals(u.getId()+""));
标签:Iterator,迭代,lastRet,elementData,cursor,new,设计模式,throw 来源: https://www.cnblogs.com/darkpar/p/16618419.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。