1

Enthuware シミュレーターからいくつかのサンプルの質問をしています。質問例はこちら

public class GoodOne
{
   int theval;
   public int hashCode()
   {
      return theval%3;
   }
   public boolean equals(Object obj)
   {
      try{
      // 1 insert code here.
      }catch(Exception e) {
        return false;
      }
   }
}

オプションを以下に示します

  1. return true;
  2. return this == obj? true : (theval%3 == 0 && ((GoodOne)obj).theval%3==0) ? true :false;
  3. return theval%2 == 0? true :false;
  4. return ( (int)Math.random())*10%3 == 0? true :false;. Math.random() が 0.0 から 1.0 (1.0 を含まない) の間の double を返すと仮定します。
  5. return false;

シミュレーターが選択した正解は、この説明が与えられたオプション 2 です。

これは、オブジェクトがtheval % 30 の場合に等しいと見なされることを意味します。さらに、2 つのオブジェクトが等しいと判断された場合、それらのハッシュコード ( theval % 3) は常に同じ (ゼロ) になります。したがって、hashCode および equals メソッドの要件を満たします。

覚えておくべき規則は次のとおりです。equals()メソッドが true を返す場合、 hashCode()2 つのオブジェクトの は同じでなければなりません。逆は望ましいですが、必須ではありません。

さらに、equals メソッドは次の規則に従う必要があります: 再帰的でなければなりません: 任意の参照値 x に対してx.equals(x)true を返す必要があります。対称である必要があります: 参照値 x および y について、x.equals(y) true を返す場合にのみ true を返す必要がありy.equals(x)ます。推移的である必要があります。x、y、および z の参照値に対して、x.equals(y) true を返し、true をy.equals(z)返す場合は、true を返すx.equals(z)必要があります。一貫性がある必要があります。参照値 x および y に対してx.equals(y)、オブジェクトの equals 比較で使用される情報が変更されていない場合、一貫して true を返すか、一貫して false を返すの複数の呼び出し。null でない参照値 x の場合、x.equals(null)false を返す必要があります。

オプション 1 は、すべてのオブジェクトが等しいと見なされ、hashCode()すべてのオブジェクトに対して同じ値を返さなければならないため、間違っていますが、そうではありません。

3 の倍数はすべて 0 であるため、オプション 2 は正しいです。hashCode()したがって、3equals()の倍数のすべてに対してメソッドで true を返すと、条件が満たされます。また、オブジェクトがそれ自体と比較された場合にも true を返します。

オプション 3 は正しくありません。2 と 6 は等しいと見なされますが、ハッシュ コードは異なります (2 と 0)。

どのオブジェクトが等しいと見なされるかを判断できないため、オプション 4 は誤りです。

その説明が理解できません。このサンプルでオプション 2 が正しい理由を誰か詳しく教えてください。ありがとう。

4

1 に答える 1

2

すべての 3 の倍数の hashCode() が 0 であるため、オプション 2 は正しいです。したがって、すべての 3 の倍数に対して equals() メソッドで true を返すと、条件が満たされます。また、オブジェクトがそれ自体と比較された場合にも true を返します。

ええと、私は言わなければなりません、これはなぜそのオプションが機能するのかを支持するひどい説明です. おそらく、equals()メソッドhashCode()自体の実装がひどいためです。現在、2 つのオブジェクトが (ある意味で) 同じハッシュコードequals()を持っている場合、メソッドはtrueを返します。その部分をもう一度見てみましょう:

return this == obj? true : (theval%3 == 0 && ((GoodOne)obj).theval%3==0) ? true :false;

まず第一に、その式は次のように改善できます (ただし、これも適切な実装ではありません)。

return this == obj? true : theval % 3 == ((GoodOne)obj).theval % 3;

theVal % 3はそのオブジェクトのハッシュコードに他なりません。したがって、基本的に、このメソッドは、ハッシュコードに基づいて 2 つのオブジェクトが等しいかどうかを判断しています。(まあ、このhashCode()方法は良い実装の例でもありません)。

equals()このメソッドの大きな問題の 1 つは、を処理できないことnullです。我が神よ。そのリソースからの読み取りを停止することをお勧めします。名前は何ですか- Enthuware

そうは言っても、この equals メソッドは、指定されたハッシュコードと連携して正常に機能します (提供され、null適切に処理されます)。equalsメソッドのコントラクトを考えてみましょう。

  • 再帰:それでいいです。a.theVal % 3 == a.theVal % 3.
  • 対称: これもいいです。2 つのオブジェクトabの場合a.theVal % 3 == b.theVal % 3、 の場合、その逆も真です。
  • 推移的- これも問題ありません。a.theVal % 3 = b.theVal % 3b.theVal % 3 == c.theVal % 3は、 を意味しa.theVal % 3 == c.theVal % 3ます。
  • 一貫性- まあ、 の場合、またはが変更されてa.theVal % 3 == b.theVal % 3いない場合、それは常に真になります。a.thevalb.theVal

equals()との間のコントラクトが来ますhashCode():

  • 2 つのオブジェクトが等しい場合、それらの hashCodes は等しくなければなりません。ハッシュコードに基づいてオブジェクトが等しいかどうかを既に判断しているため、これは確かにここに当てはまります。

したがって、これは2番目のオプションがここでどのようにうまくいくかを説明しています.


あなたが本当に心に留めておくべきこと:

覚えておくべき非常に重要な一般的なポイントの 1 つは、同じオブジェクト属性のセットを使用して、オブジェクトが等しいかどうかを判断するために使用するハッシュコードを計算する必要があるということです。そうしないと、コントラクトが壊れます。

たとえば、クラスにもう 1 つのフィールドがあり、 - と言うnameと、hashCodeメソッドは次のように変更されます。

theVal % 3 * name.hashCode();

しかし、あなたは方法を変更しませんでしたequals()。次に、2 つのオブジェクトのtheVal値が同じで名前が異なる場合、それらはメソッドの実装に従って等しくなりequals()ますが、上記の の実装を考えると、それらのハッシュコードは異なりますhashCode()


equals() と hashCode() の方が良いですか?

私は、与えられたhashCode()andequals()メソッドはあまり良い実装ではないと言いました。次に、やや良い実装と見なすことができるもの。さて、 Effective Java - Item 9を参照することをお勧めします。これは、このトピックに深く関わっています。

Eclipse IDE を使用している場合は、これら 2 つのメソッドを生成するように依頼できます。Eclipse は、equals()およびhashCode()メソッドの非常に優れた実装を生成します。

于 2013-08-25T21:05:38.750 に答える