java 原生序列化本身不支持压缩,需借助 gzipoutputstream 或 zliboutputstream 等流包装器实现。具体做法是将 objectoutputstream 包裹在压缩输出流中,写入时自动压缩字节数据,读取时反向解压并反序列化。

使用 GZIP 进行序列化压缩
通过 GZIPOutputStream 包装 ObjectOutputStream 即可实现压缩。调用 writeObject() 时,对象数据会先被序列化,再经 GZIP 算法压缩后写入底层流。

import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GzipSerializer {
public static void serialize(Object obj, String filePath) throws Exception {
try (FileOutputStream fos = new FileOutputStream(filePath);
GZIPOutputStream gzos = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(gzos)) {
oos.writeObject(obj);
}
}
public static Object deserialize(String filePath) throws Exception {
try (FileInputStream fis = new FileInputStream(filePath);
GZIPInputStream gzis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(gzis)) {
return ois.readObject();
}
}
}
预期结果:生成的文件体积显著小于未压缩的序列化文件,且 deserialize 能正确还原对象。
使用 Zlib 进行序列化压缩
使用 ZlibOutputStream(如 Apache Commons Compress 提供)可实现类似 GZIP 的压缩效果。Zlib 通常比 GZIP 略快,但兼容性稍差。用法同样是将 ObjectOutputStream 包裹在压缩流中。

import org.apache.commons.compress.compressors.z.ZCompressorOutputStream;
import java.io.*;
public class ZlibSerializer {
public static void serialize(Object obj, String filePath) throws Exception {
try (FileOutputStream fos = new FileOutputStream(filePath);
ZCompressorOutputStream zcos = new ZCompressorOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(zcos)) {
oos.writeObject(obj);
}
}
}
预期结果:与 GZIP 类似,文件体积减小,反序列化时需对应使用 ZDecompressorInputStream。
压缩对序列化性能的影响
压缩会增加 CPU 开销,因为序列化过程涉及额外的编码和解码步骤。对于大对象,压缩带来的 I/O 减少可能抵消 CPU 成本;对于小对象,CPU 开销可能超过收益。实际测试表明,当对象大小超过 1KB 时,GZIP 压缩通常能带来净收益。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











