2

プログラムの 1 つで Decorator パターンを使用して、さまざまな卒業要件を持つコースを装飾しています。いくつかの例:

new BasicCourse("Course Foo", 1);  // parameters are name and credits

new DisciplinaryBreadth(DBR.MATH, new BasicCourse("Course Foo", 1));

new IntroToHumanities(IHUM.FIRST_QUARTER,
        new ProgramInWritingAndRhetoric(PWR.FIRST_YEAR,
        new BasicCourse("Course Bar", 2)));

new ProgramInWritingAndRhetoric(PWR.FIRST_YEAR,
        new IntroToHumanities(IHUM.FIRST_QUARTER,
        new BasicCourse("Course Bar", 2)));

最後の 2 つは可換性により同じです。

HashMap で Courses を使用できるように、hashcode()andを実装しています。equals()交換可能なコースが互いに等しくなるように、Eclipse の自動生成された equals 関数を変更する必要がありました。私は等号と同様にハッシュコードの生成を理解していないので、ハッシュコード関数についても同じことをする必要があるかどうか疑問に思っています。

Eclipse が各デコレータについて私に与えたものは次のとおりです。

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((inner == null) ? 0 : inner.hashCode());
        result = prime * result
                + ((requirement == null) ? 0 : requirement.hashCode());
        return result;
    }

これは可換コースに対して同じハッシュを生成しますか?

EDIT
各デコレータには、requirementそのデコレータを含むコースが満たす要件に対応する変数があります。たとえば、DisciplinaryBreadth クラスには、可能な Disciplinary Breadth 要件の列挙であるクラス DBR の要件があります。ProgramInWritingAndRhetoric クラスにはクラス PWR の要件があります。これは、可能性のある Program in Writing および Rhetoric 要件の列挙です。等々。

各デコレーターの要件変数は異なる列挙型です。すべてのコースは、さまざまな卒業要件 (例: ) を取得するメソッドを実装していgetDbrs()ますgetIhum()

デコレーターは、定義したものを除くすべての要件に対して、内部 Course のメソッドを呼び出します。たとえば、IntroToHumanities クラスはinner.getDbrs()inner.getPwr()を呼び出しますが、メソッドには要件変数を使用しますgetIhum()。また、 BasicCourse クラスは、コンストラクターに設定された最終メンバーを使用してこれらのメソッドを定義しますが、getName()およびメソッドの内部 Course のメソッドを呼び出します。getCredits()

inner変数は、各デコレータがラップする内側の Course です。内部変数と要件変数は、各デコレーターのコンストラクターで設定され、最終的なものです。

ProgramInWritingAndRhetoric クラスの equals メソッドは次のとおりです。

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Course))
        return false;
    Course other = (Course) obj;
    if (getName() == null) {
        if (other.getName() != null)
            return false;
    } else if (!getName().equals(other.getName()))
        return false;
    if (getCredits() != other.getCredits())
        return false;
    if (!getDbrs().equals(other.getDbrs()))
        return false;
    if (!requirement.equals(other.getPwr()))
        return false;
    if (!getIhum().equals(other.getIhum()))
        return false;
    if (!getEc().equals(other.getEc()))  //another Graduation Requirement
        return false;
    return true;
}

コンストラクターでチェックするため、null のチェックの一部をスキップしました。たとえば、null IHUM を使用して Course を作成することはできません。他の Graduation Requirements は equals を同様に実装しますが、唯一の違いは要件変数が使用される場所です。

4

2 に答える 2

2

@Eva IDEにハッシュコードメソッドを生成させるべきだというアドバイスには同意しませんが、おそらく私は古風です。

基本的に、ハッシュを生成するときは、オブジェクトのメンバー変数に基づいて、(合理的に実行可能な限り)十分に分散された一意のハッシュのセットを取得することを目的としています。

したがって、メンバー変数の値(プリミティブの場合)またはハッシュコード(複雑なオブジェクトの場合)を取得し、それらを使用して、適切に分散される方法でハッシュコードを計算する必要があります(したがって、乗数として素数を一般的に使用します) )そして衝突を引き起こす可能性は低いです。

したがって、妥当なhashCode()は、equalsメソッドと同じメンバー変数を使用しますが、値/ハッシュ値を取得し、それらを素数とともに乗算します。

一意で適切に分散されたハッシュの唯一の保証は、可能なオブジェクトの完全なユニバースを事前に知ることです。この場合、実際にハッシュを事前に割り当てることができますが、それが有効な解決策になることはめったにありません。

これはあなたが達成しようとしていることのかなり良い説明です-http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/

于 2013-01-23T17:33:45.600 に答える
1

codeghost の回答に基づいて、これが適切なハッシュコードである可能性があると思います (IntroToHumanities クラス内):

public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + getCredits();
    result = prime * result + 
            ((getName() == null) ? 0 : getName().hashCode());
    result = prime * result + getDbrs().hashCode();
    result = prime * result + getPwr().hashCode();
    result = prime * result + requirement.hashCode();
    result = prime * result + getEc().hashCode();
    return result;
}
于 2013-01-23T17:51:26.707 に答える