0、前言本文主要对几种常见Java序列化方式进行实现。包括Java原生以流的方法进行的序列化、Json序列化、FastJson序列化、Protobuff序列化。 1、Java原生序列化Java原生序列化方法即通过Java原生流(InputStream和OutputStream之间的转化)的方式进行转化。需要注意的是JavaBean实体类必须实现Serializable接口,否则无法序列化。Java原生序列化代码示例如下所示: package serialize;import java.io.BufferedInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.ArrayList;import java.util.List;/** * * @author liqqc * */public class JavaSerialize { public static void main(String[] args) throws ClassNotFoundException, IOException { new JavaSerialize().start(); } public void start() throws IOException, ClassNotFoundException { User u = new User(); List
运行结果: java serialize: 8ms; 总大小:420java deserialize: 1ms; User: User [userId=null, userName=张三, passWord=123456, userInfo=张三是一个很牛逼的人, friends=[User [userId=null, userName=李四, passWord=123456, userInfo=李四是一个很牛逼的人, friends=null], User [userId=null, userName=王五, passWord=123456, userInfo=王五是一个很牛逼的人, friends=null]]]
2、Json序列化Json序列化一般会使用jackson包,通过ObjectMapper类来进行一些操作,比如将对象转化为byte数组或者将json串转化为对象。现在的大多数公司都将json作为服务器端返回的数据格式。比如调用一个服务器接口,通常的请求为xxx.json?a=xxx&b=xxx的形式。Json序列化示例代码如下所示: package serialize;import java.io.IOException;import java.util.ArrayList;import java.util.List;import com.fasterxml.jackson.databind.ObjectMapper;/** * * @author liqqc * */public class JsonSerialize { public static void main(String[] args) throws IOException { new JsonSerialize().start(); } public void start() throws IOException { User u = new User(); List
运行结果: json serialize: 55ms; 总大小:341json deserialize: 35ms; User: User [userId=null, userName=张三, passWord=123456, userInfo=张三是一个很牛逼的人, friends=[User [userId=null, userName=李四, passWord=123456, userInfo=李四是一个很牛逼的人, friends=null], User [userId=null, userName=王五, passWord=123456, userInfo=王五是一个很牛逼的人, friends=null]]]
3、FastJson序列化fastjson 是由阿里巴巴开发的一个性能很好的Java 语言实现的 Json解析器和生成器。特点:速度快,测试表明fastjson具有极快的性能,超越任其他的java json parser。功能强大,完全支持java bean、集合、Map、日期、Enum,支持范型和自省。无依赖,能够直接运行在Java SE 5.0以上版本 package serialize;import java.util.ArrayList;import java.util.List;import com.alibaba.fastjson.JSON;/** * * @author liqqc * */public class FastJsonSerialize { public static void main(String[] args) { new FastJsonSerialize().start(); } public void start(){ User u = new User(); List
运行结果: fastJson serialize: 284ms; 总大小:269fastJson serialize: 26ms; User: User [userId=null, userName=张三, passWord=123456, userInfo=张三是一个很牛逼的人, friends=[User [userId=null, userName=李四, passWord=123456, userInfo=李四是一个很牛逼的人, friends=null], User [userId=null, userName=王五, passWord=123456, userInfo=王五是一个很牛逼的人, friends=null]]]
4、ProtoBuff序列化
ProtoBuff序列化对象可以很大程度上将其压缩,可以大大减少数据传输大小,提高系统性能。对于大量数据的缓存,也可以提高缓存中数据存储量。原始的ProtoBuff需要自己写.proto文件,通过编译器将其转换为java文件,显得比较繁琐。百度研发的jprotobuf框架将Google原始的protobuf进行了封装,对其进行简化,仅提供序列化和反序列化方法。其实用上也比较简洁,通过对JavaBean中的字段进行注解就行,不需要撰写.proto文件和实用编译器将其生成.java文件,百度的jprotobuf都替我们做了这些事情了。 一个带有jprotobuf注解的JavaBean如下所示,如果你想深入学习可以参照https://github.com/google/protobuf。 package serialize;import java.io.Serializable;import java.util.List;import com.baidu.bjf.remoting.protobuf.FieldType;import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;public class User implements Serializable { private static final long serialVersionUID = -7890663945232864573L; @Protobuf(fieldType = FieldType.INT32, required = false, order = 1) private Integer userId; @Protobuf(fieldType = FieldType.STRING, required = false, order = 2) private String userName; @Protobuf(fieldType = FieldType.STRING, required = false, order = 3) private String passWord; @Protobuf(fieldType = FieldType.STRING, required = false, order = 4) private String userInfo; @Protobuf(fieldType = FieldType.OBJECT, required = false, order = 5) private List
jprotobuf序列化代码示例如下所示: package serialize;import java.io.IOException;import java.util.ArrayList;import java.util.List;import com.baidu.bjf.remoting.protobuf.Codec;import com.baidu.bjf.remoting.protobuf.ProtobufProxy;/** * * @author liqqc * */public class ProtoBuffSerialize { public static void main(String[] args) throws IOException { new ProtoBuffSerialize().start(); } public void start() throws IOException { Codec
运行结果: jprotobuf序列化耗时:9ms; 总大小:148jprotobuf反序列化耗时:0ms; User: User [userId=null, userName=张三, passWord=123456, userInfo=张三是一个很牛逼的人, friends=[User [userId=null, userName=李四, passWord=123456, userInfo=李四是一个很牛逼的人, friends=null], User [userId=null, userName=王五, passWord=123456, userInfo=王五是一个很牛逼的人, friends=null]]]
5、总结我们通过Main方法来进行对比测试,(但是通过测试发现少量数据无法准确显示每种序列化方式的优劣,故这里无法给出比较好的答案,仅供参考)。示例代码如下所示: package serialize;import java.io.IOException;/** * @author liqqc */public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException { ProtoBuffSerialize protoBuffSerialize = new ProtoBuffSerialize(); protoBuffSerialize.start(); System.err.println(); System.err.println(); JavaSerialize javaSerialize = new JavaSerialize(); javaSerialize.start(); System.err.println(); JsonSerialize jsonSerialize = new JsonSerialize(); jsonSerialize.start(); System.err.println(); FastJsonSerialize fastJsonSerialize = new FastJsonSerialize(); fastJsonSerialize.start(); }}
运行结果: jprotobuf序列化耗时:7ms; 总大小:148jprotobuf反序列化耗时:0msjava serialize: 6ms; 总大小:420java deserialize: 1msjson serialize: 37ms; 总大小:341json deserialize: 27msfastJson serialize: 173ms; 总大小:269fastJson serialize: 35ms
上面的测试仅供参考,并不能代表通过大量数据进行测试的结果。可以发现:序列化后对象的所占大小上:protobuff序列化所占总大小是最少的;其次是fastJson序列化;最后是json序列化和java原生序列化。对于序列化耗时,上面的测试不准。 还是去看看专业测试分析吧,具体情况可以进去看看https://github.com/eishay/jvm-serializers/wiki 本文仅仅简单介绍了下几种序列化方式的实现,并未经过大量测试对其进行对比分析,待后续有时间和精力在进行补充。 |
|