Javaで任意のオブジェクトをMapキーとして使用することの欠点はありますか?
-
10-07-2019 - |
質問
アプリケーションには2種類のオブジェクトがあり、1つの種類のすべてのオブジェクトに対応するもう1つの種類のオブジェクトが1つだけあります。
この関係を追跡するための明らかな選択は、HashMapのようなMap<type1, type2>
です。しかし、どういうわけか、私は不審です。オブジェクトをマップのキーとして使用し、オブジェクトを渡し、別のコレクションに配置し、いつでもマップからそのパートナーを取得できますか?
オブジェクトが作成された後、渡されるのは識別子だけですよね?おそらく問題ないでしょう。キーをシリアル化および逆シリアル化するとどうなりますか?
その他の注意事項はありますか?自分で生成した数値のように、オブジェクトペアを相関させるために他の何かを使用する必要がありますか?
解決
- キーは
.equals()
および.hashCode()
を正しく実装する必要があります - キーは、キーとして使用されている間に
HashMap
値を変更するような方法で変更しないでください - 理想的には、<=>でキーとして使用されるオブジェクトは不変でなければなりません。これにより、2。が常に真であることが自動的に保証されます。
- GCやその他の方法でGCできるオブジェクトは、キーおよび/または値として使用されるときに保持される可能性があります。
他のヒント
2種類のオブジェクトがあります 1つのすべてのオブジェクトが存在するアプリケーション kindには対応するものが1つだけあります 他の種類のオブジェクト。
これは、has-a関係のように聞こえるので、単純な属性を使用して実装できます。
選択するマップの実装に依存します:
-
HashMap は、 equals()および hashCode()を使用します。デフォルトでは(Objectで)これらはオブジェクトIDに基づいており、シリアル化/逆シリアル化しない限り問題なく動作します。オブジェクトのコンテンツに基づいてequals()とhashCode()を適切に実装すれば、ハッシュマップのキーである間は変更しない限り問題ありません。
-
TreeMap は compareTo()を使用します。デフォルトの実装はないため、実装する必要があります。上記のhashCode()およびequals()の実装と同じ制限が適用されます。
標準のマップを使用することもできますが、その場合、マップ内のオブジェクトへの強い参照を保持します。オブジェクトが別の構造で参照されており、それらをリンクするためだけにマップが必要な場合は、WeakHashMapの使用を検討してください。
ところで、オブジェクトの複数のインスタンスを等しいと見なす必要がない限り、equalsとhashCodeをオーバーライドする必要はありません...
オブジェクトをマップのキーとして使用し、それを渡し、別のコレクションに配置し、いつでもマップからそのパートナーを取得できますか?
はい、まったく問題ありません。
オブジェクトが作成された後、渡されるのは識別子だけですよね?おそらく問題ないでしょう。キーをシリアル化および逆シリアル化するとどうなりますか?
そうです、参照を渡すだけです-それらはすべて同じ実際のオブジェクトを指します。オブジェクトをシリアライズまたはデシリアライズすると、新しいオブジェクトが作成されます。ただし、オブジェクトがequalsとhashCodeを適切に実装していれば、新しいデシリアライズされたオブジェクトを使用して、マップからアイテムを取得できるはずです。
その他の注意事項はありますか?自分で生成した数値のように、オブジェクトペアを相関させるために他の何かを使用する必要がありますか?
警告に関しては、はい、オブジェクトがマップ内にある間にオブジェクトのhashCodeを変更するような変更はできません。
任意のオブジェクトをマップキーにすることができます。ここで重要なことは、マップキーとして使用されるオブジェクトの.equals()および.hashCode()を必ずオーバーライドすることです。
これを行う理由は、そうしない場合、equalsはオブジェクトの平等として理解され、<!> quot; equal <!> quot;を見つけることができる唯一の方法だからです。マップキーは、元のオブジェクト自体へのハンドルを持つことです。
等しいと一致する必要があるため、ハッシュコードをオーバーライドします。これは、定義したオブジェクトが同等にハッシュするようにするためです。
失敗ポイントはハッシュコードと同等の関数です。一貫した適切な戻り値が生成されない場合、Mapは奇妙な動作をします。 効果的なJava にはセクション全体があり、強くお勧めします。
Googleコレクションの BiMap 。