FastJson遇见的问题或项⽬实战中优化的问题,看源码都可以
解决
1:感觉见⿁了⼀般存储JSONObject中的字段竟然不见了?
JSONObject object=new JSONObject();
Map fields = new HashMap();
fields.put("1","1");
object.put("fields",fields);
System.out.String());
JSONObject newFields = JSONObject("fields");
newFields.put("2",2);
//TODO 序列化字符串没有2?!!
/
/ 看源码便可以知晓,当我们使⽤Map当做JSONObject解析时候,Fastjson会返回⼀个新的对象
System.out.String());
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 : Set()) {
Object key = Key();
String jsonKey = TypeUtils.castToString(key);
Object jsonValue = Value());
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, GlobalInstance());
JSONArray array;
JSONLexer lexer = parser.lexer;
fastjson怎么用if (ken() == JSONToken.NULL) {
array = null;
} else if (ken() == 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 = wArrayList(1, 2, 3, 5);//Lists来⾄于Guava
Integer[] iarr = new Integer[5]; // 相⽐如add(index,e)耗费时间位置所在
//对于顺序存储的ArrayList⽽⾔,toArray⽅法的底层实现也是使⽤的System.arrcopy⽅法进⾏⾼效
⽣成数组
Integer[] arr1 = Array(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.Class());
JSONArray retArr = new JSONArray(ret);
System.out.JSONString(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⽅法底层使⽤的是内存复制⽣成数组,⾼效率。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论