为什么指定Map的初始容量会导致后续的序列化产生不同的结果? [英] Why does specifying Map's initial capacity cause subsequent serializations to give different results?
问题描述
我试图比较2 我正在序列化的对象( 以下是MCVE: 由于某些原因,如果 我添加了第二次反序列化序列化并与第一次相比。他们总是平等的。注意,我必须创建一个 据我所知,初始容量只是一个性能参数 。使用默认的或指定的不应该改变行为或功能。 我使用jdk1.8.0_25和Windows7。 为什么会发生这种情况? 以下行和注释在 确实,查看字节的十六进制数,数字2(您配置的桶数)和数字16(桶的默认数量)之间。我没有检查过这个字节的含义。但如果是别的,这可能是一个巧合,因为这是唯一的区别。 I am trying to compare 2 I do not understand how these 2 arrays can be different. Deserializing the first The object I am serializing ( Here is the MCVE: For some reason, if I added a 2nd iteration of deserialization-serialization and compared to the 1st. They are always equal. The difference manifests only after the first iteration. Note that I must create a As much as I know, the initial capacity is a performance parameter only. Using the default one or a specified one should not change behavior or functionality. I am using jdk1.8.0_25 and Windows7. Why does this happen? The following line and comment in the Indeed, looking at the hex of the bytes, the difference is between a number 2 (your configured number of buckets) and a number 16 (the default number of buckets). I haven't checked that's what this particular byte means; but it'd be quite a coincidence if it's something else, considering that's the only difference.
这篇关于为什么指定Map的初始容量会导致后续的序列化产生不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! byte []
这是同一对象序列化的结果:
byte []
是通过反序列化第一个 byte []
,然后再次序列化。 数组可以不同。反序列化第一个 byte []
应该重建原始对象,并且序列化该对象与序列化原始对象相同。所以,2 byte []
应该是相同的。然而,在某些情况下它们可能是不同的,显然是。
State
)包含另一个对象( MapWrapper
)的列表,该对象又保存一个集合。取决于集合,我从比较代码中得到了不同的结果。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String [] args){
State state = new State();
state.maps.add(new MapWrapper());
byte [] pBA = stateToByteArray(state);
State pC = byteArrayToState(pBA);
byte [] zero = stateToByteArray(pC);
System.out.println(Arrays.equals(pBA,zero)); //见下面的输出
状态pC2 = byteArrayToState(pBA);
byte [] zero2 = stateToByteArray(pC2);
System.out.println(Arrays.equals(zero2,zero)); //总是为真
public static byte [] stateToByteArray(State s){
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s);
return bos.toByteArray();
} catch(IOException e){
e.printStackTrace();
}
返回null;
public static State byteArrayToState(byte [] bytes){
ObjectInputStream ois;
尝试{
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return(State)ois.readObject();
} catch(IOException | ClassNotFoundException e){
e.printStackTrace();
}
返回null;
class State实现Serializable {
private static final long serialVersionUID = 1L;
列表< MapWrapper> maps = new ArrayList<>();
}
类MapWrapper实现了Serializable {
private static final long serialVersionUID = 1L;
//不同的选项,选择一个!
//列表< Integer> ints = new ArrayList<>(); true
// List< Integer> ints = new ArrayList<>(3); true
// Map< String,Integer> map = new HashMap<>(); true
// Map< String,Integer> map = new HashMap<>(2); false
code $
MapWrapper
包含一个 HashMap
(或 LinkedHashMap
)和容量,序列化会产生与序列化 - 反序列化 - 序列化不同的结果。
MapWrapper
并将其添加到列表中。 在 State
中,就像在 main
开始时所做的那样,导致这种情况。
HashMap
readObject
的源代码解释了区别:
s.readInt(); //读取并忽略桶的数量
< snip> 08 00 00 00 02 00 00 00 78 78 // Original
< snip> 08 00 00 00 10 00 00 00 00 78 78 //反序列化+序列化。
^
byte[]
which are the results of serialization of the same object:
byte[]
is created by serializing the objectbyte[]
and then serializing it again.byte[]
should reconstruct the original object, and serializing that object is the same as serializing the original one. So, the 2 byte[]
should be the same. However, under certain circumstances they can be different, apparently.State
) holds a list of another object (MapWrapper
) which in turn holds a single collection. Depending on the collection, I get different results from my comparison code.import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) {
State state = new State();
state.maps.add(new MapWrapper());
byte[] pBA = stateToByteArray(state);
State pC = byteArrayToState(pBA);
byte[] zero = stateToByteArray(pC);
System.out.println(Arrays.equals(pBA, zero)); // see output below
State pC2 = byteArrayToState(pBA);
byte[] zero2 = stateToByteArray(pC2);
System.out.println(Arrays.equals(zero2, zero)); // always true
}
public static byte[] stateToByteArray(State s) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static State byteArrayToState(byte[] bytes) {
ObjectInputStream ois;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return (State) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
class State implements Serializable {
private static final long serialVersionUID = 1L;
List<MapWrapper> maps = new ArrayList<>();
}
class MapWrapper implements Serializable {
private static final long serialVersionUID = 1L;
// Different options, choose one!
// List<Integer> ints = new ArrayList<>(); true
// List<Integer> ints = new ArrayList<>(3); true
// Map<String, Integer> map = new HashMap<>(); true
// Map<String, Integer> map = new HashMap<>(2); false
}
MapWrapper
contains a HashMap
(or LinkedHashMap
) and is initialized with an initial capacity, the serialization gives a different result than a serialization-deserialization-serialization.MapWrapper
and add it to the list in State
, as done in the start of main
, to cause this.HashMap
source code of readObject
explains the difference:s.readInt(); // Read and ignore number of buckets
<snip> 08 00 00 00 02 00 00 00 00 78 78 // Original
<snip> 08 00 00 00 10 00 00 00 00 78 78 // Deserialized+serialized.
^