Комплекс HashMap имеет другой хэш-код после сериализации - PullRequest
2 голосов
/ 19 марта 2010

Я анализирую 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;
}

Я перезаписал все hashCode и равные методы usind EqualsBuilder и HashCodeBuilder общих лангов. Теперь, когда я копирую 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-й раз хеш-код отличается ...

Есть идеи, о чем это?

Ответы [ 3 ]

2 голосов
/ 01 сентября 2010

Хэш-код enum не согласован во всех экземплярах JVM. Вместо этого вы можете использовать хеш-код enum.toString().

1 голос
/ 19 марта 2010

Поскольку hashCode для HashMap определяется в терминах hashCode каждого ключа и значения, я бы попытался выяснить , какой ключ или элемент производит другой hashCode после сериализации.

0 голосов
/ 19 марта 2010

Хорошо, как предположил г-н Зауэр, я написал некоторый тестовый код, чтобы выяснить, какой элемент имеет другой хэш-код, и я обнаружил, что все (!) Объекты EcmField имеют разные хэш-коды, , но все Параметр EcmField получил такой же хеш-код !!

Вот реализации хеш-кода и равно:

@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))), все остальные ложные

Я не понимаю ...

...