迭代器模式
概念理解
迭代器是一个java对象,我们使用的时候可以通过迭代器中定义的通用方法去遍历java容器(所有实现了collection接口的子类,包括list、set、queue等)中存储的元素,并且无需关注java容器的底层实现(数据结构)。
java容器中对于迭代器已经实现好了我们也无需关注他是如何实现的(底层基于数组、链表、树的操作),但是当我们想使用迭代器的方法去遍历不是java已经实现的容器中的元素时需要我们自己去实现迭代器接口类遍历方法的具体细节。
list、set、queue迭代器类图
设计思路
- 定义迭代器接口类 Iterator,定义next()、hasNext()方法: 目的是进行遍历的时候如果有下一个对象就遍历下一个;
- 提供Collection接口在其实现类中引入迭代器接口类并在实现类中提供基于实现类自己底层数据结构的迭代器实现,add()和remove()方法是为了让实现类自己基于底层数据结构新增和删除对象,提供给迭代器遍历的时候使用;
- 进行list、set、queue实现类的迭代器遍历;
本文自定义迭代器类图
设计思路
- 定义迭代器接口类 Iterator,定义next()、hasNext()方法: 目的是进行遍历的时候如果有下一个对象就遍历下一个;(和list、set、queue定义迭代器接口类一样)
- 提供Collection<E,T>接口,区别是相比于上面java自身Collection容器多了addLink()、removeLink()方法是因为除了维护员工对象集合还要维护一个员工部门集合;
- 进行迭代器遍历;
本文自定义迭代器内部实现逻辑
- 确认是否有下一个
在迭代器内部定义一个变量totalIdx,每次在next()方法中遍历完之后就加1,直到totalIdx等于employeeMap(人员map)的size时就没有下一个了
public boolean hasNext() {
return totalIdx < employeeMap.size();
}
- 迭代器内部取下一个元素实现
第一次遍历toId为1,linkList为1->2,1->3,取节点2;
第二次遍历toId为2,linkList为2->4,2->5,取节点4;
第三次遍历toId为4,linkList为null,判断如果为null时通过4节点的父节点继续取4节点的兄弟节点,linkList为2->4,2->5,上面4节点已经取过了,所以取节点5;
第四次遍历toId为5,linkList为5->6,5->7,5->8,取节点6;
第五次遍历取节点7;
第六次遍历取节点8;
第七次遍历时toId为8,因为8节点没有兄弟节点所以向上取8节点的父节点5的兄弟节点,5也没有兄弟节点继续向上取5的父节点2的兄弟节点3,所以取节点3;
public Iterator<Employee> iterator() {
return new Iterator<Employee>() {
private Map<String,Integer> keyMap = new HashMap<>();
int totalIdx = 0;
String toId = gourpId;
String fromId = gourpId;
@Override
public boolean hasNext() {
return totalIdx < employeeMap.size();
}
@Override
public Employee next() {
List<Link> linkList = linkMap.get(toId);
int cursorIdx = getCursorIdx(toId);
if (null == linkList) {
linkList = linkMap.get(fromId);
cursorIdx = getCursorIdx(fromId);
}
while (cursorIdx > linkList.size() -1) {
fromId = invertedMap.get(fromId);
cursorIdx = getCursorIdx(fromId);
linkList = linkMap.get(fromId);
}
Link link = linkList.get(cursorIdx);
fromId = link.getFromId();
toId = link.getToId();
totalIdx ++;
return employeeMap.get(toId);
}
private int getCursorIdx(String key){
int idx = 0;
if (keyMap.containsKey(key)) {
idx = keyMap.get(key);
keyMap.put(key,++idx);
} else {
keyMap.put(key,idx);
}
return idx;
}
};
效果
20:53:39.035 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='2', name='花花', desc='二级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='4', name='蹦蹦', desc='三级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='5', name='大烧', desc='三级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='6', name='虎哥', desc='四级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='7', name='玲姐', desc='四级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='8', name='秋雅', desc='四级部门'}
20:53:39.041 [main] INFO cn.leilei.iterator.test.ApiTest - Employee{uId='3', name='豆包', desc='二级部门'}