2

我正在将一个 xml 文件解析为一个复杂的 HashMap,如下所示:

Map<String, Map<String, EcmObject>

Ecm对象:

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
}

EcmObject类型:

public enum EcmObjectType implements Serializable {
   FOLDER, REGISTER, DOCUMENT
}

电磁场

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 和 equal 方法。现在,当我以这种方式复制 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()不等于m2.hashCode()

这是我的输出:

-1639352210
-2071553208
1679930154

另一个奇怪的事情是,例如。10 次 m 具有相同的哈希码,突然在第 11 次哈希码不同......

有什么想法吗?

4

3 回答 3

2

的哈希码enum在 JVM 实例之间不一致。您可以使用 hashcode ofenum.toString()代替。

于 2010-09-01T10:23:53.483 回答
1

由于hashCodeaHashMap是根据hashCode每个键和值的定义来定义的,因此我会尝试找出哪个hashCode键或元素在序列化后产生不同的结果。

于 2010-03-19T11:20:16.640 回答
0

Ok, as Mr Sauer suggested, I wrote some test code to find out which element has a different hashCode and I found out, that all(!) EcmField-Objects have different hashCodes, but all of EcmField's parameter have got the same hashcode !!

Here are hashcode and equals implementations:

@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();
}

and this is my test code

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());
    }
}

And only the first two if clauses are entered (if (ecmFieldOne.hashCode() != ecmFieldTwo.hashCode()) and if (!ecmFieldOne.equals(ecmFieldsTwo))), all others are false

I don't get it...

于 2010-03-19T12:17:35.310 回答