序列化与反序列化及不同序列化方式的性能对比

在现代分布式系统中,序列化和反序列化是不可或缺的环节。它们用于将对象转换为可传输的字节流,并在接收端重建对象。本文将探讨几种常见的序列化方式,包括JSON、Java原生序列化和Protobuf,并通过实例代码进行性能对比。

序列化方式简介
  1. JSON: 简单、可读性强,但性能和体积上相对较差。
  2. Java原生序列化: Java内置,使用简单,但体积较大且性能一般。
  3. Protobuf (Protocol Buffers): Google开发的高效序列化框架,性能和体积优于JSON和Java原生序列化。
实例代码

我们将使用一个简单的类 Cat 进行序列化和反序列化测试。Cat 类包含两个属性:nameage

java 复制代码
import java.io.*;

class Cat implements Serializable {
    private String name;
    private int age;

    // Constructors, getters, and setters

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // toString method
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
JSON序列化和反序列化

我们使用 Jackson 库进行JSON序列化和反序列化。

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonSerialization {
    private static ObjectMapper objectMapper = new ObjectMapper();

    public static String serialize(Cat cat) throws IOException {
        return objectMapper.writeValueAsString(cat);
    }

    public static Cat deserialize(String json) throws IOException {
        return objectMapper.readValue(json, Cat.class);
    }
}

Java原生序列化和反序列化

java 复制代码
public class NativeSerialization {
    public static byte[] serialize(Cat cat) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            oos.writeObject(cat);
            return bos.toByteArray();
        }
    }

    public static Cat deserialize(byte[] data) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            return (Cat) ois.readObject();
        }
    }
}
Protobuf序列化和反序列化

首先,定义Protobuf的 .proto 文件:

java 复制代码
syntax = "proto3";

message Cat {
    string name = 1;
    int32 age = 2;
}

生成Java类后:

java 复制代码
import com.google.protobuf.InvalidProtocolBufferException;
import example.CatProto.Cat;

public class ProtobufSerialization {
    public static byte[] serialize(Cat cat) {
        return cat.toByteArray();
    }

    public static Cat deserialize(byte[] data) throws InvalidProtocolBufferException {
        return Cat.parseFrom(data);
    }
}
性能对比

我们通过以下代码进行性能测试:

java 复制代码
import java.io.IOException;
import java.util.Arrays;

public class SerializationPerformanceTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Cat cat = new Cat("Whiskers", 3);

        // JSON
        long jsonStart = System.nanoTime();
        String json = JsonSerialization.serialize(cat);
        Cat jsonCat = JsonSerialization.deserialize(json);
        long jsonEnd = System.nanoTime();
        System.out.println("JSON time: " + (jsonEnd - jsonStart));

        // Native
        long nativeStart = System.nanoTime();
        byte[] nativeData = NativeSerialization.serialize(cat);
        Cat nativeCat = NativeSerialization.deserialize(nativeData);
        long nativeEnd = System.nanoTime();
        System.out.println("Native time: " + (nativeEnd - nativeStart));

        // Protobuf
        example.CatProto.Cat protoCat = example.CatProto.Cat.newBuilder().setName("Whiskers").setAge(3).build();
        long protoStart = System.nanoTime();
        byte[] protoData = ProtobufSerialization.serialize(protoCat);
        example.CatProto.Cat protoCatDeserialized = ProtobufSerialization.deserialize(protoData);
        long protoEnd = System.nanoTime();
        System.out.println("Protobuf time: " + (protoEnd - protoStart));
    }
}
结论

根据测试结果,Protobuf的序列化和反序列化性能优于JSON和Java原生序列化。虽然JSON的可读性强,但在性能和体积上,Protobuf更具优势。因此,在对性能和体积有较高要求的场景下,推荐使用Protobuf进行序列化。

通过以上实例代码和测试结果,我们可以更好地理解不同序列化方式的优缺点,并根据具体需求选择合适的序列化方式。

相关推荐
程序猿阿伟2 分钟前
《探索 Apache Spark MLlib 与 Java 结合的卓越之道》
java·spark-ml·apache
向阳121811 分钟前
sentinel来源访问控制(黑白名单)
java·sentinel
Takumilove12 分钟前
MQTT入门:在Spring Boot中建立连接及测试
java·spring boot·后端
潜洋24 分钟前
Spring Boot 教程之三十六:实现身份验证
java·数据库·spring boot
TroubleMaker36 分钟前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp
cloud___fly1 小时前
Spring AOP入门
java·后端·spring
灰色孤星A1 小时前
瑞吉外卖项目学习笔记(四)@TableField(fill = FieldFill.INSERT)公共字段填充、启用/禁用/修改员工信息
java·学习笔记·springboot·瑞吉外卖·黑马程序员·tablefield·公共字段填充
逊嘘1 小时前
【Java数据结构】ArrayList相关的算法
java·开发语言
Y编程小白2 小时前
SpringBoot的创建方式
java·spring boot·后端