Set
別の要素と等しい要素を取得する操作が提供されないのはなぜですか?
Set<Foo> set = ...;
...
Foo foo = new Foo(1, 2, 3);
Foo bar = set.get(foo); // get the Foo element from the Set that equals foo
Set
に と等しい要素が含まれているかどうかを問い合わせることはできますがbar
、なぜその要素を取得できないのでしょうか? :(
明確に言うと、equals
メソッドはオーバーライドされていますが、すべてのフィールドではなく、 の 1 つのフィールドのみをチェックします。したがって、Foo
等しいと見なされる 2 つのオブジェクトが実際には異なる値を持つ場合があり、そのため を使用することはできませんfoo
。
ベストアンサー1
「なぜ、別の要素と等しい要素を取得する操作が提供されないのですかSet
?」という正確な質問に答えるには、コレクション フレームワークの設計者があまり先を見越していなかったため、という答えになります。彼らは、非常に正当な使用例を予測せず、単純に「数学的なセットの抽象化をモデル化」しようとし (javadoc より)、便利なget()
メソッドを追加することを忘れただけです。
さて、「それでは要素をどうやって取得するのか」という暗黙の質問ですが、最善の解決策はMap<E,E>
、 の代わりにを使用してSet<E>
、要素をそれら自身にマップすることだと思います。そのようにすると、の get() メソッドが効率的なハッシュ テーブルまたはツリー アルゴリズムを使用して要素を見つけるため、「セット」から要素を効率的に取得できます。必要に応じて、をカプセル化する追加のメソッドを提供するMap
の独自の実装を作成することもできます。Set
get()
Map
以下の回答は、私の意見では、悪いか間違っています。
「すでに等しいオブジェクトがあるため、要素を取得する必要はありません」: 質問で既に示しているように、この主張は間違っています。等しい 2 つのオブジェクトは、オブジェクトの等価性とは関係のない異なる状態を持つ場合があります。目標は、Set
「クエリ」として使用されるオブジェクトの状態ではなく、 に含まれる要素のこの状態にアクセスすることです。
「イテレータを使用する以外に選択肢はありません」: これはコレクションの線形検索であり、大規模なセットではまったく非効率的です (皮肉なことに、内部的にはSet
ハッシュ マップまたはツリーとして編成されており、効率的にクエリできます)。これはやめてください。このアプローチを使用すると、実際のシステムで深刻なパフォーマンスの問題が発生するのを見たことがあります。私の意見では、欠落しているget()
メソッドのひどいところは、それを回避するのが少し面倒なことではなく、ほとんどのプログラマーが影響を考えずに線形検索アプローチを使用することです。