数组比ArrayList更易于序列化吗?

4
不久前,我们的架构师向我介绍了这个想法。当时我没有更多机会与他交流,但我始终无法理解为什么数组比ArrayList更具可序列化性/性能更好。
更新:如果涉及到Web服务代码,则可能指的是性能而不是可序列化性。
更新:对于ArrayList,XML序列化没有问题。
  <sample-array-list>reddy1</sample-array-list>
  <sample-array-list>reddy2</sample-array-list>
  <sample-array-list>reddy3</sample-array-list>

分布式应用程序可能会存在问题吗?


4
我们都“喜欢”所谓的建筑师。 - Bozho
7个回答

22

“更可序列化”这种说法并不存在。一个类可以被序列化或者不能被序列化,数组和ArrayList都是可以序列化的。

至于性能,那是完全不同的话题。数组,特别是原始类型数组,使用的内存比ArrayList少得多,但对于两者来说,序列化格式实际上是一样紧凑的。

最终,唯一能够真正解释这个模糊且具有误导性的声明的人是提出它的人。我建议您询问您的架构师他到底是什么意思。


如果它们所包含的类型实现了“Serializable”,那么数组和ArrayList都是可序列化的。 - Powerlord
对于一个 ArrayList,第一个序列化对象的开销会比较高。 - Tom Hawtin - tackline
请注意,ArrayList 中的后备数组是瞬态的,并且在 writeObject 方法中进行序列化。 - Bozho
@Reddy 针对 ArrayList 类需要有一个描述符,其中包括类名、字段、字段类型等信息。如果数据不是很多,那么这可能会占据消息的相当大比例。 - Tom Hawtin - tackline

10
我假设您在谈论Java对象序列化。
事实证明,数组(对象)和ArrayList具有类似但不完全相同的内容。在数组情况下,序列化将由对象头、数组长度及其元素组成。在ArrayList情况下,序列化由列表大小、数组长度和数组的前“size”个元素组成。因此,多序列化了一个32位int。两者的对象头也可能存在差异。
因此,是的,序列化表示形式的大小存在微小的差异(可能为4个字节)。而且,数组的序列化/反序列化可能会稍微快一些。但这些差异很可能在噪声范围内,并且不值得担心...除非分析表明这是瓶颈。
编辑
根据@Tom Hawtin的评论,对象头的差异是显着的,特别是如果序列化只包含少量的ArrayList实例。

1
哈哈,是的。这是由于数组列表的额外“容量”选项,使得需要序列化数组的大小和长度。但我们都同意这不重要 :) - Bozho
“但我们将同意这是微不足道的。” 绝对同意! - Stephen C

4
也许他指的是在Web服务中使用的XML序列化?几年前我曾经使用过,记得一个返回List对象的Web服务很难连接(至少我无法想出如何连接,可能是因为ArrayListLinkedList的内部结构),尽管当返回本地数组时这很容易实现。
针对Reddy的评论,

但无论如何(数组或ArrayList) 都会被转换为XML,对吧?

是的,它们会被转换成XML,但XML序列化基本上将序列化对象中包含的所有数据转换成XML。 对于一个数组,它是一系列值。例如,如果您声明并序列化
int[] array = {42, 83};

您可能会得到一个类似于以下的XML结果:
 <array>42</array>
 <array>83</array

对于ArrayList而言,它是一个包含以下内容的数组:

  • 一个数组(显然),其大小可能大于实际元素数
  • 几个其他成员,如整数索引(firstIndexlastIndex)、计数等

(您可以在{{link1:ArrayList.java源代码}}中找到所有这些内容)

因此,所有这些都将被转换为XML,这使得Web服务客户端更难读取实际值:它必须读取索引值,找到实际数组,并读取位于两个索引之间的值。

序列化:

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(42);
list.add(83);

可能最终看起来像:

<firstIndex>0</firstIndex>
<lastIndex>2</lastIndex>
<E>42</E>
<E>83</E>
<E>0</E>
<E>0</E>
<E>0</E>
<E>0</E>
<E>0</E>
<E>0</E>
<E>0</E>
<E>0</E>

基本上,当在Web服务中使用XML序列化时,最好使用数组(例如int[])而不是集合(例如ArrayList<Integer>)。为此,您可能会发现使用Collection#toArray()将集合转换为数组非常有用。

是的,这是关于Web服务的。但无论如何(数组或ArrayList),都会被转换为XML……对吧? - Reddy
我在响应中使用了ArrayList和HashMap,并检查了XML。ArrayList没有额外的字段,而HashMap作为空标签出现。<sample-array-list>reddy1</sample-array-list> <sample-array-list>reddy2</sample-array-list> <sample-array-list>reddy3</sample-array-list> <sample-hash-map/> - Reddy
噢,有趣。我猜事情可能已经改变了,或者我的记忆不够准确...等我有机会使用NetBeans并查看产生的XML是什么样子时,我会尝试一下...如果需要的话,我会编辑我的答案。 - Axel

3

它们都将相同的数据序列化。因此,我不会说其中一个比另一个更好。


1
"它们并不完全序列化相同的数据" - 不是完全一样...请看我的回答。 - Stephen C

1
据我所知,两者都是可序列化的,但使用数组更好,因为实现ArrayList的主要目的是为了内部易于操作,而不是暴露给外部世界。它使用起来有点重,因此在使用Web服务时,在对其进行序列化时,可能会在命名空间和标头中创建问题。如果它自动设置它们,您将无法正确接收或发送数据。因此最好使用原始数组。

我不同意。如果这对于使用API的任何人更方便,那么暴露列表而不是数组没有任何问题。 - Stephen C
Bhaswanth,你能解释一下“它可能会在命名空间和头文件中造成问题”吗? - Reddy

0

只有在Java中才有所不同,即使是这样,也很难注意到。

如果他不是指Java,那么是的,你最好问他具体是什么意思。


0
只是一个相关的想法:List接口不可序列化,因此如果您想在可序列化的API中包含List,则被迫公开一个可序列化的实现,例如ArrayList或将List转换为数组。良好的设计实践不鼓励公开您的实现,这可能是为什么您的架构师鼓励您将List转换为数组的原因。将List转换为数组会付出一些时间成本,但在另一端,您可以使用java.util.Arrays.asList()将数组包装为列表接口,这很快速。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接