成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Json底層一覽

Stardustsky / 3525人閱讀

摘要:在開始了解的原理之前,首先看一段代碼,在這里以阿里的為例。翻開的源碼可以發(fā)現(xiàn),在其節(jié)點(diǎn)類里面,在的基礎(chǔ)上又添加了一個和指針,那么這兩個指針就是雙向鏈表的指針??偨Y(jié)其實(shí)每一個的設(shè)計(jì)都是很精妙的

在開始了解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());
    }
}

當(dāng)看到上述代碼的時候,可能一般的程序員都會想到的是輸出為如下Json

{"id":"a","name":"b"}
但是運(yùn)行這段程序,你會發(fā)現(xiàn)控制臺打印出來的是如下代碼:
{"name":"b","id":"a"}

那么為什么會出現(xiàn)這種情況呢,翻開FastJson的源碼便知道了,首先定位到 JsonObject 這個類的構(gòu)造函數(shù),如下:

public JSONObject(int initialCapacity, boolean ordered){
        if (ordered) {
            map = new LinkedHashMap(initialCapacity);
        } else {
            map = new HashMap(initialCapacity);
        }
    }

這里的 ordered 為一個構(gòu)造參數(shù),表示的是是否按照順序添加,此處先不管,然后可以發(fā)現(xiàn)在阿里的FastJson中,其實(shí)默認(rèn)的Json實(shí)現(xiàn)是一個Map,那么對于LinkedHashMap來講,它是一個map和雙向鏈表的整合體,所以在LinkedList中,每一個Node都會有一個前指針和一個后指針

HashMap

LinkedHashMap 是一個HashMap的變種,大家都知道,一個HashMap是由一個桶和一個桶后面的節(jié)點(diǎn)組成的,而桶其實(shí)是一個數(shù)組,每一個桶的索引所對應(yīng)的值都是由Hash()函數(shù)計(jì)算得出的。那么這樣就會導(dǎo)致桶的元素是一個亂序的存儲的,例如在本段代碼中的idname,它們所在的桶索引可能是:

這樣就導(dǎo)致了一個問題,就是Json的鍵的順序是無法保證的,那么既然HashMap是無法保證的,為什么LinkedHashMap卻可以保證順序。

LinkedHashMap

翻開LinkedHashMap的源碼可以發(fā)現(xiàn),在其節(jié)點(diǎn)類里面,LinkedHashMap在 HashMap的Entry基礎(chǔ)上又添加了一個beforeafter指針,

  static class Entry extends HashMap.Node {
        Entry before, after;
        Entry(int hash, K key, V value, Node next) {
            super(hash, key, value, next);
        }
    }

那么這兩個指針就是雙向鏈表的指針。有了這兩個指針之后,每一個新插入的節(jié)點(diǎn)都會知道他的前驅(qū)結(jié)點(diǎn)和后置節(jié)點(diǎn),那么對于LinkedHashMap的插入順序就會有保證了。所以其對應(yīng)的數(shù)據(jù)結(jié)構(gòu)如圖:

在這個結(jié)構(gòu)里面,桶索引是id的第一個節(jié)點(diǎn)是一個頭節(jié)點(diǎn),在新插入name的時候,LinkedHashMap會將head節(jié)點(diǎn)的after指針指向name,所以雖然這是一個HashMap,但是它的順序還是可以保證的。

LinkedHashMap的迭代

區(qū)別于HashMap以索引的方式進(jìn)行迭代,LinkedHashMap是以鏈表的指針進(jìn)行迭代的,如以下代碼所示:

abstract class LinkedHashIterator {
        LinkedHashMap.Entry next;
        LinkedHashMap.Entry current;
        int expectedModCount;

        LinkedHashIterator() {
            next = head;
            expectedModCount = modCount;
            current = null;
        }


final LinkedHashMap.Entry nextNode() {
            LinkedHashMap.Entry e = next;  //next就是head節(jié)點(diǎn)
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            current = e;
            next = e.after; //此處每一次的迭代都是鏈表的after
            return e;
        }

可以看到在每一次迭代的時候LinkedHashMap都是以鏈表的next節(jié)點(diǎn)作為下一個迭代,那么HashMap呢?

HashMap的迭代
abstract class HashIterator {
        Node next;        // 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的桶,所以其實(shí)HashMap的迭代就是依據(jù)桶中的順序來的,但是LinkedHashMap則是按找鏈表的順序來的。

總結(jié)

其實(shí)每一個java的設(shè)計(jì)都是很精妙的...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77055.html

相關(guān)文章

  • 近幾個月Github上最熱門的Java項(xiàng)目一覽

    摘要:今天逛了逛,順手精選出了一下近幾個月以來上最熱門的個項(xiàng)目。相關(guān)閱讀正式開源,幫助應(yīng)用快速容器化未來可能會上熱門的項(xiàng)目地址介紹哈哈,皮一下很開心。這是我自己開源的一份文檔,目前仍在完善中,歡迎各位英雄好漢一起完善。 showImg(https://segmentfault.com/img/remote/1460000015766827?w=391&h=220);今天逛了逛Github,順...

    cyqian 評論0 收藏0
  • UPYUN首創(chuàng)CDN實(shí)時監(jiān)控,性能狀態(tài)一覽無遺

    摘要:云加速服務(wù)商日前宣布,正式推出實(shí)時狀態(tài)與性能監(jiān)控功能。的實(shí)時狀態(tài)和性能監(jiān)控,覆蓋全國所有省份,幫助所有用戶直接全面了解服務(wù)情況,及時發(fā)現(xiàn)定位和解決突發(fā)問題,實(shí)現(xiàn)產(chǎn)品性能的最大優(yōu)化。 云加速服務(wù)商 UPYUN 日前宣布,正式推出 CDN 實(shí)時狀態(tài)與性能監(jiān)控功能。通過對全國 120 個 CDN 節(jié)點(diǎn)日志的數(shù)據(jù)分析,將速度、耗時、ISP 線路、地區(qū)、請求占比等多維度的精準(zhǔn)數(shù)據(jù),以地圖的方式具...

    lingdududu 評論0 收藏0
  • web 應(yīng)用常見安全漏洞一覽

    摘要:應(yīng)用常見安全漏洞一覽注入注入就是通過給應(yīng)用接口傳入一些特殊字符,達(dá)到欺騙服務(wù)器執(zhí)行惡意的命令。此外,適當(dāng)?shù)臋?quán)限控制不曝露必要的安全信息和日志也有助于預(yù)防注入漏洞。 web 應(yīng)用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應(yīng)用接口傳入一些特殊字符,達(dá)到欺騙服務(wù)器執(zhí)行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗(yàn)上的優(yōu)化。 原因 當(dāng)使用外...

    darkerXi 評論0 收藏0
  • web 應(yīng)用常見安全漏洞一覽

    摘要:應(yīng)用常見安全漏洞一覽注入注入就是通過給應(yīng)用接口傳入一些特殊字符,達(dá)到欺騙服務(wù)器執(zhí)行惡意的命令。此外,適當(dāng)?shù)臋?quán)限控制不曝露必要的安全信息和日志也有助于預(yù)防注入漏洞。 web 應(yīng)用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應(yīng)用接口傳入一些特殊字符,達(dá)到欺騙服務(wù)器執(zhí)行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗(yàn)上的優(yōu)化。 原因 當(dāng)使用外...

    Panda 評論0 收藏0
  • Android 研發(fā)工程師圖書一覽(2016年版)

    摘要:番茄工作法簡約而不簡單,本書亦然。在番茄工作法一個個短短的分鐘內(nèi),你收獲的不僅僅是效率,還會有意想不到的成就感。 @author ASCE1885的 Github 簡書 微博 CSDN 知乎本文由于潛在的商業(yè)目的,不開放全文轉(zhuǎn)載許可,謝謝! showImg(/img/remote/1460000007319503?w=728&h=792); 廣而告之時間:我的新書《Android 高...

    MadPecker 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<