FastJson遇見的問題或項目實戰中優化的問題,看源碼都可以解決


1:感覺見鬼了一般存儲JSONObject中的字段竟然不見了? 

 

        JSONObject object=new JSONObject();
        Map fields = new HashMap();
        fields.put("1","1");
        object.put("fields",fields);
        System.out.println(object.toString());
        JSONObject newFields = object.getJSONObject("fields");
        newFields.put("2",2);
        //TODO  序列化字符串沒有2?!!
        // 看源碼便可以知曉,當我們使用Map當做JSONObject解析時候,Fastjson會返回一個新的對象
        System.out.println(object.toString());

  

com.alibaba.fastjson.JSON#toJSON(java.lang.Object, com.alibaba.fastjson.serializer.SerializeConfig)源碼:

 public static Object toJSON(Object javaObject, SerializeConfig config) {
        if (javaObject == null) {
            return null;
        }

        if (javaObject instanceof JSON) {
            return javaObject;
        }

        if (javaObject instanceof Map) {
            Map<Object, Object> map = (Map<Object, Object>) javaObject;
        // 創建了一個新的JSONObject返回了
            JSONObject json = new JSONObject(map.size());

            for (Map.Entry<Object, Object> entry : map.entrySet()) {
                Object key = entry.getKey();
                String jsonKey = TypeUtils.castToString(key);
                Object jsonValue = toJSON(entry.getValue());
                json.put(jsonKey, jsonValue);
            }

            return json;
        }

  

2:當我們使用JSONArray時候,有些時候里面可能存儲較大量的數據,但是有些場景需要在指定index處進行insert操作,這時由於JSONArray默認底層使用的是ArrayList存儲,因此存在性能問題,那么是否可以使用LinkedList呢?答案可以的:

 JSONArray arr = new JSONArray(new LinkedList());

  

3:當我們查詢接口獲取到一個JSONArray字符串想反序列化時候可否將底層存儲的ArrayList使用LinkedList替換呢?答案:可以,修改一下源碼或者添加一個重載方法即可。

 public static JSONArray parseArray(String text) {
        if (text == null) {
            return null;
        }

        DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance());

        JSONArray array;

        JSONLexer lexer = parser.lexer;
        if (lexer.token() == JSONToken.NULL) {
            lexer.nextToken();
            array = null;
        } else if (lexer.token() == JSONToken.EOF) {
            array = null;
        } else {
//            array = new JSONArray(new ArrayList());
            array = new JSONArray(new LinkedList());
            parser.parseArray(array);

            parser.handleResovleTask(array);
        }

        parser.close();

        return array;
    }

 

4:當我們調用方法返回一個含有大量的元素的JSONArray時候該如何進行插入?

問題3中的是字符串我們解析時候可以自定義解析為LinkedList,但是當我們獲取的是一個JSONArray時候該如何處理?難道還有序列化字符串在反序列化到底層存儲為LinkedList的JSONArray嗎?答案不需要,我們可以借助java的System的arrcopy方法高效完成轉換:

     //加入我們有一個比較大的list,想在中間高效插入元素
        List<Integer> list = Lists.newArrayList(1, 2, 3, 5);//Lists來至於Guava
        Integer[] iarr = new Integer[5]; // 相比如add(index,e)耗費時間位置所在
     //對於順序存儲的ArrayList而言,toArray方法的底層實現也是使用的System.arrcopy方法進行高效生成數組 Integer[] arr1 = list.toArray(new Integer[0]); Integer[] arr2 = new Integer[]{1, 2, 3}; //TODO 高效復制 System.arraycopy(arr1, 0, iarr, 0, 3); //模擬中間插入元素 iarr[3] = 4; //TODO 高效復制 System.arraycopy(arr1, 3, iarr, 4, 1); //java.util.Arrays.ArrayList // Arrays的asList方法效率高,原因是直接將傳入的數組作為Arrays.ArrayList的底層存儲容器 List ret = Arrays.asList(iarr); System.out.println(ret.getClass()); JSONArray retArr = new JSONArray(ret); System.out.println(JSON.toJSONString(retArr));

 該點存在錯誤,經過實際測試發現該方案比ArraList的add(index,e)普遍要慢,原因首先還是看一下ArrayList的add(index,e)方法:

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

  看源碼可以發現add(index,e)使用的也是arraycopy,那為什么要快呢?認真看arraycopy的參數都是elementData,而且該數組通常容量都是已經擴容好的,在極有少數情況下需要擴容。但是上述4中的方法需要我們自己初始化一個數組,該數組大小等於current+addSize,初始化該數組比較耗費時間。 

注意: JDK的ArrayList擴容使用的是內存復制,並不是逐個移動元素。JDK開發者還是很聰明的。

 

5:在4中我們可以發現使用素組高效創建ArrayList的方法時:

List ret = Arrays.asList(1,2,3,4);

底層不是進行for循環逐個插入,而是直接使用數組作為ArrayList的底層存儲。

 

但是需要特別注意:

此處的ArrayList不是java.util.ArrayList,而是class java.util.Arrays.ArrayList 。但是class java.util.Arrays.ArrayList也是java.util.List的子類實現,由於java多態存在因此不存在類型的限制。

 

6: 同於順序存儲的ArrayList的toArray方法底層使用的是內存復制生成數組,高效率。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM