做者:小傅哥
博客: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