摘要:在開始了解的原理之前,首先看一段代碼,在這里以阿里的為例。翻開的源碼可以發現,在其節點類里面,在的基礎上又添加了一個和指針,那么這兩個指針就是雙向鏈表的指針。總結其實每一個的設計都是很精妙的
在開始了解Json的原理之前,首先看一段代碼,在這里以阿里的FastJson為例。
public class JsonRun { public static void main(String[] args) { JSONObject jsonObject =new JSONObject(); jsonObject.put("id","a"); jsonObject.put("name","b"); System.out.println(jsonObject.toJSONString()); } }
當看到上述代碼的時候,可能一般的程序員都會想到的是輸出為如下Json串
{"id":"a","name":"b"}
但是運行這段程序,你會發現控制臺打印出來的是如下代碼:
{"name":"b","id":"a"}
那么為什么會出現這種情況呢,翻開FastJson的源碼便知道了,首先定位到 JsonObject 這個類的構造函數,如下:
public JSONObject(int initialCapacity, boolean ordered){ if (ordered) { map = new LinkedHashMap(initialCapacity); } else { map = new HashMap (initialCapacity); } }
這里的 ordered 為一個構造參數,表示的是是否按照順序添加,此處先不管,然后可以發現在阿里的FastJson中,其實默認的Json實現是一個Map,那么對于LinkedHashMap來講,它是一個map和雙向鏈表的整合體,所以在LinkedList中,每一個Node都會有一個前指針和一個后指針
HashMapLinkedHashMap 是一個HashMap的變種,大家都知道,一個HashMap是由一個桶和一個桶后面的節點組成的,而桶其實是一個數組,每一個桶的索引所對應的值都是由Hash()函數計算得出的。那么這樣就會導致桶的元素是一個亂序的存儲的,例如在本段代碼中的id和name,它們所在的桶索引可能是:
這樣就導致了一個問題,就是Json的鍵的順序是無法保證的,那么既然HashMap是無法保證的,為什么LinkedHashMap卻可以保證順序。
LinkedHashMap翻開LinkedHashMap的源碼可以發現,在其節點類里面,LinkedHashMap在 HashMap的Entry基礎上又添加了一個before和after指針,
static class Entryextends HashMap.Node { Entry before, after; Entry(int hash, K key, V value, Node next) { super(hash, key, value, next); } }
那么這兩個指針就是雙向鏈表的指針。有了這兩個指針之后,每一個新插入的節點都會知道他的前驅結點和后置節點,那么對于LinkedHashMap的插入順序就會有保證了。所以其對應的數據結構如圖:
在這個結構里面,桶索引是id的第一個節點是一個頭節點,在新插入name的時候,LinkedHashMap會將head節點的after指針指向name,所以雖然這是一個HashMap,但是它的順序還是可以保證的。
LinkedHashMap的迭代區別于HashMap以索引的方式進行迭代,LinkedHashMap是以鏈表的指針進行迭代的,如以下代碼所示:
abstract class LinkedHashIterator { LinkedHashMap.Entrynext; LinkedHashMap.Entry current; int expectedModCount; LinkedHashIterator() { next = head; expectedModCount = modCount; current = null; } final LinkedHashMap.Entry nextNode() { LinkedHashMap.Entry e = next; //next就是head節點 if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); current = e; next = e.after; //此處每一次的迭代都是鏈表的after return e; }
可以看到在每一次迭代的時候LinkedHashMap都是以鏈表的next節點作為下一個迭代,那么HashMap呢?
HashMap的迭代abstract class HashIterator { Nodenext; // next entry to return Node current; // current entry int expectedModCount; // for fast-fail int index; // current slot HashIterator() { expectedModCount = modCount; Node [] t = table; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry do {} while (index < t.length && (next = t[index++]) == null); } } final Node nextNode() { Node [] t; Node e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { do {} while (index < t.length && (next = t[index++]) == null); } return e; }
注意這一段代碼
if (t != null && size > 0) { // advance to first entry do {} while (index < t.length && (next = t[index++]) == null); }
這一段代碼的作用是找出table[]中第一個不為null的桶,所以其實HashMap的迭代就是依據桶中的順序來的,但是LinkedHashMap則是按找鏈表的順序來的。
總結其實每一個java的設計都是很精妙的...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77055.html
摘要:今天逛了逛,順手精選出了一下近幾個月以來上最熱門的個項目。相關閱讀正式開源,幫助應用快速容器化未來可能會上熱門的項目地址介紹哈哈,皮一下很開心。這是我自己開源的一份文檔,目前仍在完善中,歡迎各位英雄好漢一起完善。 showImg(https://segmentfault.com/img/remote/1460000015766827?w=391&h=220);今天逛了逛Github,順...
摘要:云加速服務商日前宣布,正式推出實時狀態與性能監控功能。的實時狀態和性能監控,覆蓋全國所有省份,幫助所有用戶直接全面了解服務情況,及時發現定位和解決突發問題,實現產品性能的最大優化。 云加速服務商 UPYUN 日前宣布,正式推出 CDN 實時狀態與性能監控功能。通過對全國 120 個 CDN 節點日志的數據分析,將速度、耗時、ISP 線路、地區、請求占比等多維度的精準數據,以地圖的方式具...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的命令。此外,適當的權限控制不曝露必要的安全信息和日志也有助于預防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優化。 原因 當使用外...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的命令。此外,適當的權限控制不曝露必要的安全信息和日志也有助于預防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優化。 原因 當使用外...
摘要:番茄工作法簡約而不簡單,本書亦然。在番茄工作法一個個短短的分鐘內,你收獲的不僅僅是效率,還會有意想不到的成就感。 @author ASCE1885的 Github 簡書 微博 CSDN 知乎本文由于潛在的商業目的,不開放全文轉載許可,謝謝! showImg(/img/remote/1460000007319503?w=728&h=792); 廣而告之時間:我的新書《Android 高...
閱讀 3541·2021-11-22 11:59
閱讀 947·2021-09-27 13:36
閱讀 3608·2021-09-24 09:47
閱讀 2255·2021-09-01 11:39
閱讀 974·2021-08-31 09:37
閱讀 2308·2021-08-05 10:01
閱讀 1669·2019-08-30 15:55
閱讀 699·2019-08-30 15:54