做者:小傅哥
博客:https://bugstack.cn - 原创系列专题文章
html
沉淀、分享、成长,让本身和他人都能有所收获!😄
相信相信的力量!
java
从懵懂的少年,到拿起键盘,能够写一个HelloWorld。多数人在这并不会感受有多难,也不会认为作不出来。由于这样的例子,有老师的指导、有书本的例子、有前人的经验。但随着你的开发时间愈来愈长,要解决更复杂的问题或者技术创新,所以在网上搜了几天几夜都没有答案,这个时候是否想过放弃,仍是一直坚持不断的尝试一点点完成本身内心要的结果。每每这种没有前车可鉴须要本身解决问题的时候,可能真的会折磨到要崩溃,但你要愿意执着、愿意倔强,愿意选择相信相信的力量,就必定能解决。哪怕解决不了,也能够在这条路上摸索出其余更多的收获,为后续前进的道路填充好垫脚石。设计模式
时间紧是写垃圾代码的理由?
数组
拧螺丝?Ctrl+C、Ctrl+V?贴膏药同样写代码?没有办法,没有时间,每每真的是借口,胸中没用笔墨,才只能凑合。难道必定是好好写代码就浪费时间,拼凑CRUD就快吗,根本不可能的。由于不会,没用实操过,不多架构出全场景的设计,才很难写出优良的代码。多加强自身的编码(武术
)修为,在各类编码场景中让本身变得老练,才好应对紧急状况下的需求开发和人员安排。就像韩信同样有谋有略,才能执掌百万雄兵。微信
不要只是作个工具人!
数据结构
由于平常的编写简单业务需求,致使本身像个工具人同样,日久天长的也就不多去深刻学习更多技术栈。看见有工具、有组件、有框架,拿来就用用,反正没什么体量也不会出什么问题。但若是你想要更多的收入,哪怕是重复的造轮子,你也要去尝试造一个,就算不用到生产,本身玩玩总能够吧。有些事情只有本身经历过,才能有最深的感触,参与过实践过,才好总结点评学习。架构
bugstack虫洞栈
,回复源码下载
获取(打开获取的连接,找到序号18)工程 | 描述 |
---|---|
itstack-demo-design-15-00 | 开发树形组织架构关系迭代器 |
迭代器模式,常见的就是咱们平常使用的iterator
遍历。虽然这个设计模式在咱们的实际业务开发中的场景并很少,但却几乎天天都要使用jdk
为咱们提供的list
集合遍历。另外加强的for循环虽然是循环输出数据,可是他不是迭代器模式。迭代器模式的特色是实现Iterable
接口,经过next
的方式获取集合元素,同时具有对元素的删除等操做。而加强的for循环是不能够的。框架
这种设计模式的优势是可让咱们以相同的方式,遍历不一样的数据结构元素,这些数据结构包括;数组
、链表
、树
等,而用户在使用遍历的时候并不须要去关心每一种数据结构的遍历处理逻辑,从让使用变得统一易用。工具
在本案例中咱们模拟迭代遍历输出公司中树形结构的组织架构关系中雇员列表学习
大部分公司的组织架构都是金字塔结构,也就这种树形结构,分为一级、二级、三级等部门,每一个组织部门由雇员填充,最终体现出一个总体的树形组织架构关系。
通常咱们经常使用的遍历就是jdk默认提供的方法,对list集合遍历。可是对于这样的偏业务特性较大的树形结构,若是须要使用到遍历,那么就能够本身来实现。接下来咱们会把这个组织层次关系经过树形数据结构来实现,并完成迭代器功能。
在实现迭代器模式以前能够先阅读下java
中list
方法关于iterator
的实现部分,几乎全部的迭代器开发都会按照这个模式来实现,这个模式主要分为如下几块;
add
、remove
、iterator
等核心方法。Collection
继承。hasNext
、next
,会在具体的数据结构中写实现方式。除了这样通用的迭代器实现方式外,咱们的组织关系结构树,是由节点和节点间的关系链构成,因此会比上述的内容多一些入参。
itstack-demo-design-15-02 └── src ├── main │ └── java │ └── org.itstack.demo.design │ ├── group │ │ ├── Employee.java │ │ ├── GroupStructure.java │ │ └── Link.java │ └── lang │ ├── Collection.java │ ├── Iterable.java │ └── Iterator.java └── test └── java └── org.itstack.demo.design.test └── ApiTest.java
迭代器模式模型结构
/** * 雇员 */ public class Employee { private String uId; // ID private String name; // 姓名 private String desc; // 备注 // ...get/set }
/** * 树节点链路 */ public class Link { private String fromId; // 雇员ID private String toId; // 雇员ID // ...get/set }
A to B
、B to C
、B to D
,以此描述出一套完整的树组织结构。public interface Iterator<E> { boolean hasNext(); E next(); }
java
的jdk
中提供的是同样的,这样也方面后续读者能够对照list
的Iterator
进行源码学习。hasNext
,判断是否有下一个元素、next
,获取下一个元素。这个在list
的遍历中是常常用到的。public interface Iterable<E> { Iterator<E> iterator(); }
Iterator
的获取,也就是后续在本身的数据结构中须要实现迭代器的功能并交给Iterable
,由此让外部调用方进行获取使用。public interface Collection<E, L> extends Iterable<E> { boolean add(E e); boolean remove(E e); boolean addLink(String key, L l); boolean removeLink(String key); Iterator<E> iterator(); }
Collection
,同时继承了另一个接口Iterable
的方法iterator()
。这样后续谁来实现这个接口,就须要实现上述定义的一些基本功能;添加元素
、删除元素
、遍历
。<E, L>
,由于咱们的数据结构一个是用于添加元素,另一个是用于添加树节点的链路关系。public class GroupStructure implements Collection<Employee, Link> { private String groupId; // 组织ID,也是一个组织链的头部ID private String groupName; // 组织名称 private Map<String, Employee> employeeMap = new ConcurrentHashMap<String, Employee>(); // 雇员列表 private Map<String, List<Link>> linkMap = new ConcurrentHashMap<String, List<Link>>(); // 组织架构关系;id->list private Map<String, String> invertedMap = new ConcurrentHashMap<String, String>(); // 反向关系链 public GroupStructure(String groupId, String groupName) { this.groupId = groupId; this.groupName = groupName; } public boolean add(Employee employee) { return null != employeeMap.put(employee.getuId(), employee); } public boolean remove(Employee o) { return null != employeeMap.remove(o.getuId()); } public boolean addLink(String key, Link link) { invertedMap.put(link.getToId(), link.getFromId()); if (linkMap.containsKey(key)) { return linkMap.get(key).add(link); } else { List<Link> links = new LinkedList<Link>(); links.add(link); linkMap.put(key, links); return true; } } public boolean removeLink(String key) { return null != linkMap.remove(key); } public Iterator<Employee> iterator() { return new Iterator<Employee>() { HashMap<String, Integer> keyMap = new HashMap<String, Integer>(); int totalIdx = 0; private String fromId = groupId; // 雇员ID,From private String toId = groupId; // 雇员ID,To public boolean hasNext() { return totalIdx < employeeMap.size(); } public Employee next() { List<Link> links = linkMap.get(toId); int cursorIdx = getCursorIdx(toId); // 同级节点扫描 if (null == links) { cursorIdx = getCursorIdx(fromId); links = linkMap.get(fromId); } // 上级节点扫描 while (cursorIdx > links.size() - 1) { fromId = invertedMap.get(fromId); cursorIdx = getCursorIdx(fromId); links = linkMap.get(fromId); } // 获取节点 Link link = links.get(cursorIdx); toId = link.getToId(); fromId = link.getFromId(); totalIdx++; // 返回结果 return employeeMap.get(link.getToId()); } // 给每一个层级定义宽度遍历进度 public 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; } }; } }
new Iterator<Employee>
。雇员列表
、组织架构关系;id->list
。当元素添加元素的时候,会分别在不一样的方法中向map
结构中进行填充指向关系(A->B),也就构建出了咱们的树形组织关系。迭代器实现思路
@Test public void test_iterator() { // 数据填充 GroupStructure groupStructure = new GroupStructure("1", "小傅哥"); // 雇员信息 groupStructure.add(new Employee("2", "花花", "二级部门")); groupStructure.add(new Employee("3", "豆包", "二级部门")); groupStructure.add(new Employee("4", "蹦蹦", "三级部门")); groupStructure.add(new Employee("5", "大烧", "三级部门")); groupStructure.add(new Employee("6", "虎哥", "四级部门")); groupStructure.add(new Employee("7", "玲姐", "四级部门")); groupStructure.add(new Employee("8", "秋雅", "四级部门")); // 节点关系 1->(1,2) 2->(4,5) groupStructure.addLink("1", new Link("1", "2")); groupStructure.addLink("1", new Link("1", "3")); groupStructure.addLink("2", new Link("2", "4")); groupStructure.addLink("2", new Link("2", "5")); groupStructure.addLink("5", new Link("5", "6")); groupStructure.addLink("5", new Link("5", "7")); groupStructure.addLink("5", new Link("5", "8")); Iterator<Employee> iterator = groupStructure.iterator(); while (iterator.hasNext()) { Employee employee = iterator.next(); logger.info("{},雇员 Id:{} Name:{}", employee.getDesc(), employee.getuId(), employee.getName()); } }
22:23:37.166 [main] INFO org.itstack.demo.design.test.ApiTest - 二级部门,雇员 Id:2 Name:花花 22:23:37.168 [main] INFO org.itstack.demo.design.test.ApiTest - 三级部门,雇员 Id:4 Name:蹦蹦 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 三级部门,雇员 Id:5 Name:大烧 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:6 Name:虎哥 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:7 Name:玲姐 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 四级部门,雇员 Id:8 Name:秋雅 22:23:37.169 [main] INFO org.itstack.demo.design.test.ApiTest - 二级部门,雇员 Id:3 Name:豆包 Process finished with exit code 0
雇员 Id:二、雇员 Id:4...雇员 Id:3