2

次のような複雑な HashMap に xml ファイルを解析しています。

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
}

EcmObjectType:

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

Ecmフィールド

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 および equal メソッドを、commons lang の 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

もう1つの奇妙なことは、たとえば。10 回 m は同じハッシュコードを持ち、11 回目に突然ハッシュコードが異なります...

これが何であるかについてのアイデアはありますか?

4

3 に答える 3

2

のハッシュコードは、enumJVMインスタンス間で一貫していません。代わりにのハッシュコードを使用できますenum.toString()

于 2010-09-01T10:23:53.483 に答える
1

hashCodeは各キーと値のHashMap観点から定義されているため、シリアル化後にどのキーまたは要素が別の を生成するかhashCodeを調べようとします。hashCode

于 2010-03-19T11:20:16.640 に答える
0

OK、Sauer 氏が提案したように、どの要素が異なる hashCode を持っているかを調べるテスト コードを書いたところ、すべての (!) EcmField オブジェクトが異なる hashCode を持っているが、EcmField のすべてのパラメーターが同じhashcode を持っていることがわかりました!!

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

そして最初の 2 つの if 節のみが入力され (if (ecmFieldOne.hashCode() != ecmFieldTwo.hashCode())if (!ecmFieldOne.equals(ecmFieldsTwo)))、他のすべては false です。

理解できません...

于 2010-03-19T12:17:35.310 に答える