質問 2 への答えは簡単です。はい、好きなオブジェクトを使用できます。String 型のキーを持つマップは、ネーム サービスの典型的なデータ構造であるため、広く使用されています。Map<Car,Vendor>
ただし、一般に、またはのような任意の 2 つの型をマップできますMap<Student,Course>
。
hashcode() メソッドについては、前に答えたようなものです - equals() をオーバーライドするときはいつでも、契約に従うために hashcode() をオーバーライドする必要があります。一方、equals() の標準実装に満足している場合は、hashcode() に触れるべきではありません (これにより、契約が破られ、等しくないオブジェクトに対して同一のハッシュコードが生成される可能性があるため)。
実用的な補足事項: eclipse (およびおそらく他の IDE も同様) は、クラス メンバーに基づいて、クラスの equals() と hashcode() の実装のペアを自動生成できます。
編集
追加の質問について: はい、正確に。HashMap.get(Object key); のソース コードを見てください。key.hashcode を呼び出して、内部ハッシュ テーブル内の位置 (ビン) を計算し、その位置の値を返します (存在する場合)。
ただし、「手作り」の hashcode/equals メソッドには注意してください。オブジェクトをキーとして使用する場合は、後でハッシュコードが変更されないようにしてください。そうしないと、マップされた値が見つからなくなります。つまり、equals と hashcode を計算するために使用するフィールドは、final (またはオブジェクトの作成後は「変更不可」) である必要があります。
String name
andとの連絡先がありString phonenumber
、両方のフィールドを使用して equals() と hashcode() を計算するとします。次に、彼の携帯電話番号を使用して "John Doe" を作成し、彼をお気に入りのドーナツ ショップにマップします。hashcode() は、ハッシュ テーブルのインデックス (ビン) を計算するために使用され、そこにドーナツ ショップが格納されます。
ここで、彼が新しい電話番号を持っていることを知り、John Doe オブジェクトの電話番号フィールドを変更します。これにより、新しいハッシュコードが生成されます。そして、このハッシュコードは新しいハッシュ テーブル インデックスに解決されます。これは通常、John Does のお気に入りのドーナツ ショップが格納されていた場所ではありません。
問題は明らかです。この場合、「John Doe と特定の電話番号」ではなく、「John Doe」をドーナツ ショップにマップする必要がありました。そのため、自動生成された equals/hashcode に注意して、それらが本当に必要なものであることを確認する必要があります。不要なフィールドが使用され、HashMaps と HashSets に問題が発生する可能性があるためです。
編集 2
オブジェクトを HashSet に追加すると、オブジェクトは内部ハッシュ テーブルのキーになり、値は設定されますが使用されません (オブジェクトの静的インスタンスにすぎません)。openjdk 6 (b17) の実装は次のとおりです。
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}