Java處理JSON數據有三個比較流行的類庫FastJSON、Gson和Jackson。本文將測試這三個類庫在JSON序列化和反序列化的方面表現,主要測試JSON序列化和反序列化的速度。爲了防止因爲內存致使測試結果出現誤差,測試中對JVM內存配置-Xmx4g -Xms4g。html
測試樣本數量爲100000個,爲了保證每一個類庫在測試中都能處理同一個樣本,先把樣本Java對象保存在文件中。每一個類庫測試3次,每次循環測試10遍,去掉最快速度和最慢速度,對剩下的8遍求平均值做爲最終的速,取3次測試中最好的平均速度做爲最終的測試數據。java
類庫 | 樣本數量 | 執行次數 | 最長時間(毫秒) | 最短期(毫秒) | 平均時間(毫秒) |
---|---|---|---|---|---|
FastJSON | 100000 | 10 | 2291.22 | 1416.70 | 1454.93 |
Jackson | 100000 | 10 | 1980.92 | 841.91 | 880.82 |
Gson | 100000 | 10 | 2383.02 | 1469.08 | 1520.38 |
從測試數據可知,FastJSON和GsonJSON序列化的速度差很少,Jackson是最快的(用時Gson少大約600毫秒)。json
測試樣本數量爲100000個,爲了保證每一個類庫在測試中都能處理同一個樣本,先把樣本JSON對象保存在文件中。每一個類庫測試3次,每次循環測試10遍,去掉最快速度和最慢速度,對剩下的8遍求平均值做爲最終的速,取3次測試中最好的平均速度做爲最終的測試數據。app
類庫 | 樣本數量 | 執行次數 | 最長時間(毫秒) | 最短期(毫秒) | 平均時間(毫秒) |
---|---|---|---|---|---|
FastJSON | 100000 | 10 | 7942.31 | 6340.55 | 6526.41 |
Jackson | 100000 | 10 | 7957.22 | 6623.85 | 6815.41 |
Gson | 100000 | 10 | 8235.15 | 7006.06 | 7364.75 |
從測試數據可知,三個類庫在反序列化上性能比較接近,Gson稍微差一些。dom
把Java對象JSON序列化,Jackson速度最快,在測試中比Gson快接近50%,FastJSON和Gson速度接近。
把JSON反序列化成Java對象,FastJSON、Jackson速度接近,Gson速度稍慢,不過差距很小。性能
樣本對象包括Boolean、Int、Long、Double、Date、String、List和Map字段,其中List長度和Map的Key數量能夠根據須要改測試
import java.util.ArrayList;
import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; /** * 該類提供生成樣本的元數據 * @author accountwcx@qq.com * */ public class DataBuilder { private static final String[] chars = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; private static final int charNum = 62; // 樣本String最大長度 private static final int maxStrLength = 100; // 樣本String默認長度 private static final int defaultStrLength = 50; // 樣本List最大長度 private static final int maxListSize = 100; // 樣本List默認長度 private static final int defaultListSize = 10; // 樣本Map最大Key數量 private static final int maxMapSize = 100; // 樣本Map默認Key數量 private static final int defaultMapSize = 10; // 樣本Map中Value的數據類型 private static final String[] types = new String[] { "boolean", "int", "long", "double", "date", "string"}; private static final int typeNum = 6; private static final Random random = new Random(); /** * 生成隨機長度的字符串 * @return 字符串 */ public static String randomString(){ return randomString(random.nextInt(maxStrLength)); } /** * 生成指定長度的字符串 * @param len 字符串長度 * @return */ public static String randomString(int len) { if (len < 1 || len > maxStrLength) { // 若是字符串長度超出範圍,使用默認長度 len = defaultStrLength; } StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++) { sb.append(chars[random.nextInt(charNum)]); } return sb.toString(); } /** * 生成List樣本,List中元素的數量隨機 * @return */ public static List<String> randomStringList() { return randomStringList(random.nextInt(maxListSize)); } /** * 生成List樣本 * @param size List中元素的數量 * @return */ public static List<String> randomStringList(int size) { if (size < 1 || size > maxListSize) { size = defaultListSize; } List<String> list = new ArrayList<String>(); for (int i = 0; i < size; i++) { list.add(randomString(random.nextInt(maxStrLength))); } return list; } /** * 生成隨機Map樣本,樣本中key的數量隨機 * @return */ public static Map<String, Object> randomMap() { return randomMap(random.nextInt(maxMapSize)); } /** * 生成隨機Map樣本 * @param size 樣本中key的數量 * @return */ public static Map<String, Object> randomMap(int size) { if (size < 1 || size > maxMapSize) { size = defaultMapSize; } Map<String, Object> map = new HashMap<String, Object>(); for (int i = 0; i < size; i++) { String type = types[random.nextInt(typeNum)]; if ("boolean".equals(type)) { map.put("key" + i, random.nextBoolean()); } else if ("int".equals(type)) { map.put("key" + i, random.nextInt()); } else if ("long".equals(type)) { map.put("key" + i, random.nextLong()); } else if ("double".equals(type)) { map.put("key" + i, random.nextDouble()); } else if ("date".equals(type)) { map.put("key" + i, new Date()); } else if ("string".equals(type)) { map.put("key" + i, randomString(random.nextInt(maxStrLength))); } } return map; } }
import java.io.Serializable;
import java.util.Date; import java.util.List; import java.util.Map; import java.util.Random; /** * 樣本對象 * @author accountwcx@qq.com * */ public class SampleEntity implements Serializable { private static final long serialVersionUID = -1520171788566678009L; private Boolean fieldBoolean; private Integer fieldInt; private Long fieldLong; private Double fieldDouble; private Date fieldDate; private String fieldStr; private List<String> fieldList; private Map<String, Object> fieldMap; /** * 隨機樣本 */ public SampleEntity() { Random random = new Random(); fieldBoolean = random.nextBoolean(); fieldInt = random.nextInt(); fieldLong = random.nextLong(); fieldDouble = random.nextDouble(); fieldDate = new Date(); fieldStr = DataBuilder.randomString(); fieldList = DataBuilder.randomStringList(); fieldMap = DataBuilder.randomMap(); } /** * 指定List元素數量和Map元素數量的樣本 * @param listSize List元素數量 * @param mapKeyNum Map元素數量 */ public SampleEntity(int listSize, int mapKeyNum) { Random random = new Random(); fieldBoolean = random.nextBoolean(); fieldInt = random.nextInt(); fieldLong = random.nextLong(); fieldDouble = random.nextDouble(); fieldDate = new Date(); fieldStr = DataBuilder.randomString(); fieldList = DataBuilder.randomStringList(listSize); fieldMap = DataBuilder.randomMap(mapKeyNum); } public Boolean getFieldBoolean() { return fieldBoolean; } public void setFieldBoolean(Boolean fieldBoolean) { this.fieldBoolean = fieldBoolean; } public Integer getFieldInt() { return fieldInt; } public void setFieldInt(Integer fieldInt) { this.fieldInt = fieldInt; } public Long getFieldLong() { return fieldLong; } public void setFieldLong(Long fieldLong) { this.fieldLong = fieldLong; } public Double getFieldDouble() { return fieldDouble; } public void setFieldDouble(Double fieldDouble) { this.fieldDouble = fieldDouble; } public Date getFieldDate() { return fieldDate; } public void setFieldDate(Date fieldDate) { this.fieldDate = fieldDate; } public String getFieldStr() { return fieldStr; } public void setFieldStr(String fieldStr) { this.fieldStr = fieldStr; } public List<String> getFieldList() { return fieldList; } public void setFieldList(List<String> fieldList) { this.fieldList = fieldList; } public Map<String, Object> getFieldMap() { return fieldMap; } public void setFieldMap(Map<String, Object> fieldMap) { this.fieldMap = fieldMap; } }
import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.LinkedList; import java.util.List; import com.alibaba.fastjson.JSON; /** * 建立樣本 * @author accountwcx@qq.com * */ public class SampleBuilder { public static void main(String[] args) { int sampleSize = 100000; String jsonDataPath = "d:\\samples_json.dat"; String objectDataPath = "d:\\samples_object.dat"; buildJsonSamples(sampleSize, 10, 10, jsonDataPath); buildObjectSamples(sampleSize, 10, 10, objectDataPath); } public static List<String> loadJSONSamples(String filePath) { List<String> list = new LinkedList<String>(); File file = new File(filePath); if (!file.exists()) { return list; } BufferedReader br = null; try { br = new BufferedReader(new FileReader(file)); String line = br.readLine(); while(line != null){ list.add(line); line = br.readLine(); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != br) { try { br.close(); } catch (IOException e) { } } } return list; } @SuppressWarnings("unchecked") public static List<SampleEntity> loadSamples(String filePath) { List<SampleEntity> list = new LinkedList<SampleEntity>(); File file = new File(filePath); if (!file.exists()) { return list; } ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(file)); list = (List<SampleEntity>) ois.readObject(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != ois) { try { ois.close(); } catch (IOException e) { } } } return list; } /** * 建立樣本 * * @param sampleSize 樣本數量 * @param listSize 樣本List長度 * @param mapKeyNum 樣本Map的Key數量 * @return 樣本List */ public static List<SampleEntity> buildSamples(int sampleSize, int listSize, int mapKeyNum) { List<SampleEntity> list = new LinkedList<SampleEntity>(); for (int i = 0; i < sampleSize; i++) { list.add(new SampleEntity(listSize, mapKeyNum)); } return list; } /** * 用默認參數建立樣本,其中listSize默認爲10,mapKeyNum默認爲10。 * * @param sampleSize * @return 樣本List */ public static List<SampleEntity> buildSamples(int sampleSize) { List<SampleEntity> list = new LinkedList<SampleEntity>(); for (int i = 0; i < sampleSize; i++) { list.add(new SampleEntity()); } return list; } /** * 建立樣本,並把樣本JSON序列化,保存到文件中。 * * @param sampleSize 樣本數量 * @param listSize 樣本List長度 * @param mapKeyNum 樣本Map中Key的數量 * @param filePath 樣本輸出的文件路徑 */ public static void buildJsonSamples(int sampleSize, int listSize, int mapKeyNum, String filePath) { File file = new File(filePath); File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } if (file.exists()) { file.delete(); } List<SampleEntity> list = buildSamples(sampleSize, listSize, mapKeyNum); StringBuilder sb = new StringBuilder(); for (SampleEntity item : list) { sb.append(JSON.toJSONString(item)); sb.append("\n"); } BufferedWriter bw = null; try { file.createNewFile(); bw = new BufferedWriter(new FileWriter(file)); bw.write(sb.toString()); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != bw) { try { bw.close(); } catch (IOException e) { } } } } public static void buildJsonSamples(int sampleSize, String filePath) { File file = new File(filePath); File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } if (file.exists()) { file.delete(); } List<SampleEntity> list = buildSamples(sampleSize); StringBuilder sb = new StringBuilder(); for (SampleEntity item : list) { sb.append(JSON.toJSONString(item)); sb.append("\n"); } BufferedWriter bw = null; try { file.createNewFile(); bw = new BufferedWriter(new FileWriter(file)); bw.write(sb.toString()); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != bw) { try { bw.close(); } catch (IOException e) { } } } } public static void buildObjectSamples(int sampleSize, String filePath) { List<SampleEntity> list = buildSamples(sampleSize); File file = new File(filePath); File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } if (file.exists()) { file.delete(); } ObjectOutputStream oos = null; try { file.createNewFile(); oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(list); } catch (IOException e) { e.printStackTrace(); } finally { if (null != oos) { try { oos.close(); } catch (IOException e) { } } } } /** * 生成樣本對象,並保存到指定文件 * * @param sampleSize 樣本大小 * @param listSize 樣本中List字段長度 * @param mapKeyNum 樣本中Map對象Key數量 * @param filePath 樣本輸出的路徑 */ public static void buildObjectSamples(int sampleSize, int listSize, int mapKeyNum, String filePath) { List<SampleEntity> list = buildSamples(sampleSize, listSize, mapKeyNum); File file = new File(filePath); File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } if (file.exists()) { file.delete(); } ObjectOutputStream oos = null; try { file.createNewFile(); oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(list); } catch (IOException e) { e.printStackTrace(); } finally { if (null != oos) { try { oos.close(); } catch (IOException e) { } } } } }from: http://www.voidcn.com/blog/ZHOU452840622/article/p-6094386.html