复杂的HashMap序列化后有不同的hashCode

发布于 2024-08-25 13:52:41 字数 2236 浏览 3 评论 0原文

我正在将 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;
}

我已通过使用 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() 不等于 to m2.hashCode()

这是我的输出:

-1639352210
-2071553208
1679930154

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

有什么想法吗?

I am parsing a xml file into a complex HashMap looking like this:

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

and EcmFieldControlType

public enum EcmFieldControlType implements Serializable{
    DEFAULT, CHECKBOX, LIST, DBLIST, TEXTAREA, HIERARCHY, TREE, GRID, RADIO, PAGECONTROL, STATIC;
}

I have overwritten all hashCode and equal methods by usind commons lang's EqualsBuilder and HashCodeBuilder. Now when I copy a A HashMap this way:

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() is not equal to m2.hashCode()

here is my output:

-1639352210
-2071553208
1679930154

Another strange thing is, that eg. 10 times m has the same hashcode and suddenly on the 11th time the hashcode is different...

Any ideas what this is about?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

疯了 2024-09-01 13:52:41

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

Hashcode of enum is not consistent across JVM instances. You can use hashcode of enum.toString() instead.

末が日狂欢 2024-09-01 13:52:41

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

Since the hashCode of a HashMap is defined in terms of the hashCode of each key and value, I'd try to find out which key or element produces a different hashCode after serialization.

风铃鹿 2024-09-01 13:52:41

好的,正如 Sauer 先生所建议的,我编写了一些测试代码来找出哪个元素具有不同的 hashCode,我发现所有(!)EcmField-Objects 都有不同的 hashCode,但是所有 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))),所有其他都是假的

我不明白......

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文