当前位置: 首页 > 后端技术 > Java

手写自定义迭代器,秒懂迭代器底层原理

时间:2023-04-01 18:50:16 Java

本文节选自迭代器模式的UML类图《设计模式就该这样学》如下图。1 手写自定义集合迭代器总的来说,迭代器模式很简单。仍然以在线课程为例,我们创建一个课程集合,集合中的每一个元素都是一个课程对象,然后写一个迭代器来读出每个课程对象的信息。首先创建集合元素课程Course类。公共课程课程{私人字符串名称;公共课程(字符串名称){this.name=name;}publicStringgetName(){返回名称;}}然后创建自定义迭代器Iterator接口。publicinterfaceIterator{Enext();booleanhasNext();}创建自定义课程集合CourseAggregate接口。公共接口CourseAggregate{无效添加(课程课程);无效删除(课程课程);Iteratoriterator();}然后分别实现iterator接口和collection接口,创建IteratorImpl实现类。公共类IteratorImpl实现Iterator{privateList列表;私有整数游标;私有E元素;publicIteratorImpl(Listlist){this.list=list;}publicEnext(){System.out.print("当前位置"+cursor+":");元素=list.get(游标);游标++;返回元素;}publicbooleanhasNext(){if(cursor>list.size()-1){returnfalse;}返回真;publicclassCourseAggregateImplimplementsCourseAggregate{privateListcourseList;}}创建课程集合C??ourseAggregateImpl实例。publicCourseAggregateImpl(){this.courseList=newArrayList();}publicvoidadd(Coursecourse){courseList.add(course);}publicvoidremove(Coursecourse){courseList.remove(course);}publicIteratoriterator(){returnnewIteratorImpl(courseList);}}最后编写客户端测试代码。publicstaticvoidmain(String[]args){Coursejava=newCourse("JavaArchitecture");CoursejavaBase=newCourse("Java简介");课程设计=新课程(“Java设计模式”);Courseai=newCourse("人工智能");CourseAggregatecourseAggregate=newCourseAggregateImpl();courseAggregate.add(java);courseAggregate.add(javaBase);courseAggregate.add(设计);courseAggregate.add(ai);out.println("-----课程列表-----");打印课程(课程聚合);courseAggregate.remove(ai);System.out.println("-----删除操作后的课程列表-----");打印课程(课程聚合);}publicstaticvoidprintCourses(CourseAggregatecourseAggregate){Iteratoriterator=courseAggregate.iterator();while(!iterator.hasNext()){课程课程=迭代器。下一个();System.out.println("《" + course.getName() + "》");}}运行结果如下图所示。看到这里,小伙伴们一定有一种似曾相识的感觉,不禁让人想起每天都在使用的JDK自带的集合迭代器。让我们看看源代码中迭代器是如何使用的。2 iterator模式在JDK源码中的应用我们先来看看JDK中大家非常熟悉的Iterator源码。publicinterfaceIterator{booleanhasNext();E下一步();默认voidremove(){thrownewUnsupportedOperationException("remove");}defaultvoidforEachRemaining(Consumeraction){Objects.requireNonNull(action);while(hasNext())action.accept(next());}}从上面的代码我们看到主要定义了两个方法:hasNext()方法和next()方法,完全是我们自己写的,大家一致。另外,从上面的代码中,我们看到remove()方法很眼熟。其实是在组合模式下看到的。迭代器模式和组合模式之间似乎有一定的相似性。组合模式解决了统一树形结构每一层访问接口的问题,迭代器模式解决了统一各个集合对象元素的遍历接口的问题。虽然它们的适配场景不同,但核心理念是一致的。接下来看Iterator的实现类。其实我们常用的ArrayList中有一个内部实现类Itr,它实现了Iterator接口。公共类ArrayListextendsAbstractListimplementsList,RandomAccess,Cloneable,java.io.Serializable{...privateclassItrimplementsIterator{intcursor;//要返回的下一个元素的索引intlastRet=-1;//返回的最后一个元素的索引;-1如果没有这样的intexpectedModCount=modCount;publicbooleanhasNext(){returncursor!=size;}@SuppressWarnings("unchecked")publicEnext(){checkForComodification();inti=游标;如果(i>=size)抛出新的NoSuchElementException();对象[]elementData=ArrayList.this.elementData;if(i>=elementData.length)抛出新的ConcurrentModificationException();游标=i+1;返回(E)元素数据[lastRet=i];}...}...}其中,hasNext()方法和next()方法的实现也很简单,继续往下看,ArrayList内部还有几个迭代器进一步扩展了Itr。先看ListItrprivateclassListItrextendsItrimplementsListIterator{ListItr(intindex){super();游标=索引;}publicbooleanhasPrevious(){返回光标!=0;}publicintnextIndex(){返回光标;}publicintpreviousIndex(){returncursor-1;}...}增加了hasPrevious()方法,主要用于判断是否存在上一个元素。此外,还有子集合的SubList迭代处理。3 迭代器模式在MyBatis源码中的应用当然迭代器模式在MyBatis中也是必不可少的,我们来看一个DefaultCursor类。publicclassDefaultCursorimplementsCursor{...privatefinalCursorIteratorcursorIterator=newCursorIterator();...}实现了Cursor接口,定义了一个成员变量cursorIterator,其定义类型为CursorIterator。继续查看CursorIterator类的源码,发现它是DefaultCursor的内部类,实现了JDK中的Iterator接口。