我正在将xml文件解析为复杂的HashMap,如下所示:
Map<String, Map<String, EcmObject>
EcmObject:
public class EcmObject implements Comparable, Serializable {
private final EcmObjectType type;
private final String name;
private final List<EcmField> fields;
private final boolean pages;
// getter, equals, hashCode
}
EcmObjectType:
public enum EcmObjectType implements Serializable {
FOLDER, REGISTER, DOCUMENT
}
EcmField
public class EcmField implements Comparable, Serializable {
private final EcmFieldDataType dataType;
private final EcmFieldControlType controlType;
private final String name;
private final String dbname;
private final String internalname;
private final Integer length;
// getter, equals, hashCode
}
EcmFieldDataType
public enum EcmFieldDataType implements Serializable {
TEXT, DATE, NUMBER, GROUP, DEC;
}
和EcmFieldControlType
public enum EcmFieldControlType implements Serializable{
DEFAULT, CHECKBOX, LIST, DBLIST, TEXTAREA, HIERARCHY, TREE, GRID, RADIO, PAGECONTROL, STATIC;
}
我已经用usind commons lang的EqualsBuilder和HashCodeBuilder覆盖了所有hashCode和相同的方法。现在,当我以这种方式复制A HashMap时:
Map<String, Map<String, EcmObject>> m = EcmUtil.convertXmlObjectDefsToEcmEntries(new File("e:\\objdef.xml"));
Map<String, Map<String, EcmObject>> m2;
System.out.println(m.hashCode());
ByteArrayOutputStream baos = new ByteArrayOutputStream(8 * 4096);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(m);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
m2 = (Map<String, Map<String, EcmObject>>) ois.readObject();
System.out.println(m.hashCode());
System.out.println(m2.hashCode());
m.hashCode()
这是我的输出:
-1639352210
-2071553208
1679930154
另一个奇怪的是,例如。 10次m具有相同的哈希码,并且第11次哈希码突然不同......
任何想法是什么意思?
答案 0 :(得分:2)
enum
的Hashcode在JVM实例中不一致。您可以使用enum.toString()
的哈希码代替。
答案 1 :(得分:1)
由于hashCode
的{{1}}是根据每个键和值的HashMap
定义的,我会尝试找出哪个键或元素在序列化后生成不同的hashCode
。
答案 2 :(得分:0)
好的,正如Sauer先生建议的那样,我写了一些测试代码,找出哪个元素有不同的hashCode,我发现,所有(!)EcmField-Objects都有不同的hashCodes,但是全部EcmField的参数有相同哈希码!!
这是hashcode和equals实现:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EcmField ecmField = (EcmField) o;
return new EqualsBuilder()
.appendSuper(super.equals(o))
.append(controlType, ecmField.controlType)
.append(dataType, ecmField.dataType)
.append(dbname, ecmField.dbname)
.append(internalname, ecmField.internalname)
.append(length, ecmField.length)
.append(name, ecmField.name)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(13, 37)
.append(controlType)
.append(dataType)
.append(dbname)
.append(internalname)
.append(length)
.append(name)
.hashCode();
}
这是我的测试代码
EcmField ecmFieldOne = ecmFieldsOne.get(i);
EcmField ecmFieldTwo = ecmFieldsTwo.get(i);
if (ecmFieldOne.hashCode() != ecmFieldTwo.hashCode()) {
if (!ecmFieldOne.equals(ecmFieldsTwo)) {
System.out.println("Field: " + ecmFieldOne.getName() + " != " + ecmFieldTwo.getName());
}
if (ecmFieldOne.getControlType().hashCode() != ecmFieldTwo.getControlType().hashCode()) {
System.out.println("ControlType: " + ecmFieldOne.getControlType() + " != " + ecmFieldTwo.getControlType());
}
if (ecmFieldOne.getDataType().hashCode() != ecmFieldTwo.getDataType().hashCode()) {
System.out.println("DataType: " + ecmFieldOne.getDataType() + " != " + ecmFieldTwo.getDataType());
}
if (ecmFieldOne.getDbname().hashCode() != ecmFieldTwo.getDbname().hashCode()) {
System.out.println("Dbname: " + ecmFieldOne.getDbname() + " != " + ecmFieldTwo.getDbname());
}
if (ecmFieldOne.getInternalname().hashCode() != ecmFieldTwo.getInternalname().hashCode()) {
System.out.println("Internalname: " + ecmFieldOne.getInternalname() + " != " + ecmFieldTwo.getInternalname());
}
if (ecmFieldOne.getLength().hashCode() != ecmFieldTwo.getLength().hashCode()) {
System.out.println("Length: " + ecmFieldOne.getLength() + " != " + ecmFieldTwo.getLength());
}
if (ecmFieldOne.getName().hashCode() != ecmFieldTwo.getName().hashCode()) {
System.out.println("Name: " + ecmFieldOne.getName() + " != " + ecmFieldTwo.getName());
}
}
只输入前两个if子句(if (ecmFieldOne.hashCode() != ecmFieldTwo.hashCode())
和if (!ecmFieldOne.equals(ecmFieldsTwo))
),其他所有子句都是假的
我不明白......