arraylist序列化优化关键在于控制字段参与、采用紧凑格式或自定义读写:默认elementdata已用transient排除,只需重写writeobject/readobject精简内容;externalizable可完全接管;kryo/fst/jackson等库更高效;改用不可变list(如list.of)亦可减少冗余。

ArrayList 序列化默认走 Java 原生序列化机制,会把整个底层数组(包括未使用的空位)和 size 字段一起写入,造成体积膨胀和性能浪费。要优化,关键不是“重写序列化”,而是**控制哪些字段参与序列化、用更紧凑的格式替代原生流、或跳过序列化直接自定义读写逻辑**。
用 transient 排除底层数组,手动控制序列化内容
ArrayList 的 elementData 是 transient 的,本就不参与默认序列化。真正被序列化的只有 size 和 modCount(后者只在 debug 模式下有用),以及通过 writeObject 方法手动写出实际元素。所以你无需额外加 transient,但可以重写 writeObject 和 readObject 来精简:
- 只序列化前
size个有效元素,跳过 elementData 中冗余容量 - 避免调用默认
defaultWriteObject()写出 modCount(除非需要 fail-fast 调试) - 在
readObject中先调用defaultReadObject()恢复 size,再用readObject()逐个读元素并add(),确保容量自动扩容
实现 Externalizable 完全接管序列化流程
比 Serializable 更彻底:不保存任何字段,完全由你决定怎么写、怎么读。适合对序列化格式有强控制需求的场景(如跨语言兼容、最小体积):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
writeExternal(ObjectOutput out)中先写size,再循环写每个元素(可配合out.writeUTF()、out.writeInt()等类型化方法,比ObjectOutputStream更省空间) -
readExternal(ObjectInput in)中先读size,再循环in.readXXX()并add()元素 - 注意:必须保证读写的顺序、类型、数量严格一致,否则抛
IOException
用更高效的序列化库替代原生机制
Java 原生序列化慢、体积大、不跨语言。换成 Kryo、FST 或 Jackson(搭配 jackson-databind)能显著提升效率:
- Kryo 默认关闭注册模式 + 开启即时序列化,ArrayList 序列化后体积可减少 50% 以上,速度提升 3~5 倍
- FST 对集合类做了深度优化,支持零拷贝反序列化,适合高频 RPC 场景
- Jackson 把 ArrayList 当作 JSON 数组处理,可读性强,配合
@JsonInclude(NON_NULL)还能跳过 null 元素
避免序列化 —— 改用可序列化的不可变替代品
如果业务允许,用 List.of()(Java 9+)、Guava 的 ImmutableList 或 Vavr 的 List 替代 ArrayList。它们通常:
- 内部结构更紧凑(如扁平数组、共享结构)
- 序列化时天然只存数据,无 modCount、capacity 等冗余字段
- 部分实现(如 Vavr List)自带高效二进制序列化协议
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










