有项目需要传输Map结构的数据,有人倾向用Java序列化来做,有人倾向用JSON的序列化来做。所以我们还是比比吧。
Java观点:Object2Object,使用时简单快速。
JSON观点:JSON格式与语言无关,扩展性强,速度也应该不慢。
大家可能对Java序列化都有一个错误的认识,认为Java序列化比JSON的序列化效率高并且序列化的数据小,其实实际上并不一定是这样,我这次就想通过实际测试来解开这个谜团。
测试同一个Map<String,Object>并序列化为byte[],并再将byte[]反序列化为Map<String,Object>的过程。Object中包括String,Integer,Long,Boolean,Float,Double常规类型的数据。
序列化:Map<String,Object> -> byte[]
反序列化:byte[] -> Map<String,Object>
测试各种大小不同的Map,并循环执行同一操作N次,来得到一个相对稳定的线性结果。
手写Java(1.6.0_32)与Common Lang3(3.1)的SerializationUtils。
将采用Gson(2.2.2)与json-smart(2.0-RC2)两种不同的JSON解析器。json-smart号称是速度最快的JSON解析器。
序列化时间比较(y为序列化时间ms)
反序列化时间比较(y为反序列化时间ms)
序列化时间汇总比较(y为序列化与反序列化总时间ms)
序列化后byte大小比较(由于同类线重合显示为2条线)
序列化时间比较(y为序列化时间ms)
反序列化时间比较(y为反序列化时间ms)
序列化时间汇总比较(y为序列化与反序列化总时间ms)
序列化后byte大小比较(由于同类线重合显示为2条线)
Map在小于100时:
Java的反序列化时的性能要比Java序列化时性能差很多,1.5倍左右差距。
JSON序列化性能明显由于Java序列化性能,尤其是反序列化过程。并且序列化后的数据大小也是JSON格式的小。
Map在大于100小于1000时:
Java的反序列化时的性能并没有随Map的大小变化而变差。
JSON阵营中Gson在序列化过程中,比Java只快了那么一点点。在反序列化过程中Gson开始领先与Java,但在Map的大小过700多以后,Gson的反序列化性能比Java要慢。但JSON阵营中的json-smart依然表现出色完全是两个级别。
并不是Java的序列化速度总是最快体积最小,Java需要考虑对象类型,属性类型与内部对象信息等一系列对数据本身并不相关的内容的处理。JSON以固定的格式,稳定简单的数据结构大大简化了序列化过程,虽然也要创建新的Java数据对象但并不会比Java反序列化的速度慢。
从测试结果上看JSON的json-smart更适合项目的需要。
SerializationTest接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package
org.noahx.javavsjson;
import
java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: noah
* Date: 3/8/13
* Time: 9:59 PM
* To change this template use File | Settings | File Templates.
*/
public
interface
SerializationTest {
public
String getTestName();
public
Map<String, Object> testBytes2Map(
byte
[] bytes);
public
byte
[] testMap2Bytes(Map<String, Object> map);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package
org.noahx.javavsjson;
import
java.io.*;
import
java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: noah
* Date: 3/8/13
* Time: 10:05 PM
* To change this template use File | Settings | File Templates.
*/
public
class
JavaSerializationTest
implements
SerializationTest {
@Override
public
String getTestName() {
return
"Java"
;
}
@Override
public
Map<String, Object> testBytes2Map(
byte
[] bytes) {
Map<String, Object> result =
null
;
try
{
ByteArrayInputStream byteArrayInputStream =
new
ByteArrayInputStream(bytes);
ObjectInputStream inputStream =
new
ObjectInputStream(byteArrayInputStream);
result = (Map<String, Object>) inputStream.readObject();
inputStream.close();
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
return
result;
}
@Override
public
byte
[] testMap2Bytes(Map<String, Object> map) {
byte
[] bytes =
null
;
try
{
ByteArrayOutputStream byteArrayOutputStream =
new
ByteArrayOutputStream();
ObjectOutputStream outputStream =
new
ObjectOutputStream(byteArrayOutputStream);
outputStream.writeObject(map);
outputStream.close();
bytes = byteArrayOutputStream.toByteArray();
}
catch
(IOException e) {
e.printStackTrace();
}
return
bytes;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package
org.noahx.javavsjson;
import
org.apache.commons.lang3.SerializationUtils;
import
java.io.Serializable;
import
java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: noah
* Date: 3/9/13
* Time: 2:24 AM
* To change this template use File | Settings | File Templates.
*/
public
class
CommonLang3SerializationTest
implements
SerializationTest {
@Override
public
String getTestName() {
return
"Commons Lang3"
;
}
@Override
public
Map<String, Object> testBytes2Map(
byte
[] bytes) {
return
(Map<String, Object>) SerializationUtils.deserialize(bytes);
}
@Override
public
byte
[] testMap2Bytes(Map<String, Object> map) {
return
SerializationUtils.serialize((Serializable) map);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
package
org.noahx.javavsjson;
import
com.google.gson.Gson;
import
java.io.UnsupportedEncodingException;
import
java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: noah
* Date: 3/8/13
* Time: 10:02 PM
* To change this template use File | Settings | File Templates.
*/
public
class
GsonSerializationTest
implements
SerializationTest {
private
Gson gson;
public
GsonSerializationTest() {
gson =
new
Gson();
}
@Override
public
String getTestName() {
return
"Gson"
;
}
@Override
public
Map<String, Object> testBytes2Map(
byte
[] bytes) {
Map<String, Object> result =
null
;
try
{
result = gson.fromJson(
new
String(bytes,
"UTF-8"
), Map.
class
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
result;
}
@Override
public
byte
[] testMap2Bytes(Map<String, Object> map) {
String str = gson.toJson(map);
byte
[] bytes =
null
;
try
{
bytes = str.getBytes(
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
bytes;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
package
org.noahx.javavsjson;
import
net.minidev.json.JSONObject;
import
net.minidev.json.JSONValue;
import
net.minidev.json.parser.ParseException;
import
java.io.UnsupportedEncodingException;
import
java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: noah
* Date: 3/9/13
* Time: 1:30 AM
* To change this template use File | Settings | File Templates.
*/
public
class
JsonSmartSerializationTest
implements
SerializationTest {
@Override
public
String getTestName() {
return
"Json Smart"
;
}
@Override
public
Map<String, Object> testBytes2Map(
byte
[] bytes) {
Map<String, Object> map =
null
;
try
{
map = (Map<String, Object>) JSONValue.parseStrict((
new
String(bytes,
"UTF-8"
)));
}
catch
(ParseException e) {
e.printStackTrace();
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
map;
}
@Override
public
byte
[] testMap2Bytes(Map<String, Object> map) {
String str = JSONObject.toJSONString(map);
byte
[] result =
null
;
try
{
result = str.getBytes(
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
result;
}
}
|
源码下载:http://sdrv.ms/12ECmgG
P.S.
我也测试过Map<String,String>固定数据类型value只为String的情况,这时Java与JSON的性能的差距会减小,但JSON序列化性能与数据大小还是占优势,尤其是反序列化的速度JSON更出色。
Gson在数值反序列化后,因为Object无法确定类型,Map中的Long,Integer,Float统一转为了Double类型。
json-smart不一样,如果整数超过Integer的范围转Long,没有超过转Integer。浮点Float转为Double类型。