2011-12-16 7 views
7

TreeSetにはコンパイラーを使用するコンストラクターがあります。つまり、オブジェクトを格納するオブジェクトがComparableオブジェクトではなくても、カスタムコンパイラーを提供できます。HashSet/HashMap(カスタムハッシャー)のTreeSet/TreeMap

非順序集合の類似の実装はありますか? (例えば、オブジェクト自身の実装では異なる場合があり物体Tのためのequals()hashCode()を算出し、「調理人」オブジェクトを受け取りHashSet<T>の代替?)

C++ std::hash_setは、Javaのための何かがあるかどう思っ、あなたにこれを提供します。


編集:@Maxは、約equals()について十分な技術的ポイントをもたらします。 TreeMapHashMapのキーの場合は、Map.containsKey()経由で真です。しかし、そこに他のよく知られているデータ構造があり、それはカスタムハッシャーによる編成を可能にしますか?

+0

Set<HasherWrapper<Foo>> set = new HashSet<HasherWrapper<Foo>>(); set.add(new HasherWrapper(foo)); ... 

ラッパークラスは、次のようになりますか?一般に、アプリケーションのドメイン内にあるオブジェクトに新しいメソッドを追加することは問題ありません。たとえば、生成されたAxisクライアントから受け取ったオブジェクトのマップを作成しようとすると、WebServiceのドメインとアプリケーションのドメインが混在しています。つまり、本質的にあなたが求めるものは決して必要ではないということです。 – bezmax

答えて

9

いいえ、 "hasher"オブジェクトを持つことは、Collections仕様ではサポートされていません。これをサポートする独自のコレクションを実装することもできますが、別の方法としてHasherを代わりにHashSetに格納するラッピングオブジェクトとみなすことができます。あなたが別のオブジェクトのドメインを混合していないことを確認している、ところで

private class HasherWrapper<T> { 
    T wrappedObject; 
    public HasherWrapper(T wrappedObject) { 
     this.wrappedObject = wrappedObject; 
    } 
    @Override 
    public int hashCode() { 
     // special hash code calculations go here 
    } 
    @Override 
    public boolean equals(Object obj) { 
     // special equals code calculations go here 
    } 
} 
+1

質問に対する良い解決策。一つの提案として、 'wrappedObject'をfinalにする必要があります。さらに、 'wrappedObject'はgetterでpublicまたはprivateでなければなりません。 –

+0

最終的な理由は?それは本当にホットスポットでそれほど助けてくれますか?それがプライベートクラスであるとすれば、外部クラスがゲッターなしでフィールドにアクセスすることを許可します。 – Gray

+0

Web参照の多くは、VMがスマートで、何かが上書きされているかどうかを知っているため、最終的なものは最近必要ではないと言います。 http://stackoverflow.com/questions/4279420/does-use-of-final-keyword-in-java-improve-the-performance – Gray

0

hashcode()equals()はオブジェクトの定義属性であり、変更する必要はありません。それらは、オブジェクトを互いに等しくするものを定義し、これはセットとは異なるものであってはなりません。あなたが話していることをする唯一の方法は、オブジェクトをサブクラス化して新しいhashcode()equals()を書くことです。これは、スーパークラス 'hashcode()に加えて追加する必要がある定義変数がサブクラスに含まれていればおよびequals()。私はこれがあなたが目指しているものではないかもしれないが、これが助けてくれることを願っています。あなたがこれを望むためにあなたの推論をもっと説明すれば、それが存在すればもっと良い解決策を見つけるのに役立つでしょう。

+5

実際には、プログラム内のオブジェクトをハッシュして比較する方法は、オブジェクトの属性を定義するのではなく、プログラムの属性を定義することです。あなたが特定の問題の設定に適していることを知っている別のハッシングアルゴリズムを使用したい、または同じ名前、同じID、または何か他のものがあるとオブジェクトが等しいと考えることは、間違いではありません。これはプログラムに依存しますが、これはJavaの設計が必要な領域です。 –

1

いいえ、指定することはできません。また、TreeSetComparatorという使い方を誤解しています。 TreeSet Javadocから

:それは正しくSetインタフェースを実装し にある場合(明示的 コンパレータが提供されているかどうか)のセットによって維持順序付けがequalsと一貫性がなければならないことを

注意。 (等価との一貫性の正確な定義については、 を参照してください)これは です。これは、Setインタフェースが等価演算で定義されているため、 ですが、TreeSetインスタンスは、 compareToこの方法では と等しいと見なされる2つの要素は、セットの観点からは等しい。 のセットの動作は、順序が矛盾する場合でも正しく定義されます。 と等しい。 Set インターフェイスの一般契約に従わないだけです。 Comparable javadocから

:クラスCの自然順序付けを と一致するように言われている

はe1.compareTo(E2)== 0と同じブール値 を有する場合にのみ等しいですe.equals(null)がfalseを返すにもかかわらず、nullは、どのクラスのインスタンスでも ではなく、ecompareTo(null)は NullPointerExceptionをスローする必要があることに注意してください。Collection javadocから

:このコレクションは 指定された要素が含まれている場合

ブールは、真(オブジェクトo)

戻り値が含まれています。より正式には、この コレクションに、(o == null? e == null:o.equals(e))などの少なくとも1つの要素eが含まれている場合にのみtrueを返します。

したがって、仕様によってCollection<E>インターフェースと完全を実装するクラスのいずれかの種類が存在することができないオブジェクトを挿入するために、いくつかの外部のコンパレータスタイルのオブジェクトに依存します。オブジェクトが既に挿入されているかどうかを確認するには、すべてのコレクションでObjectクラスのequalsメソッドを使用する必要があります。

+0

私はequalsと一貫している別のカスタムコンパレータを提供できない理由を理解しようとしています。 e2.compareTo(e1)はこれを達成しません(順序が逆転しますが、等しい項目は同じです)。 –

+0

Collectionインタフェースの仕様は、名前のComparatorのプログラマ実装に依存します。 Collectionインタフェースは、実装の** all **が 'a。は(b)と等しくなります。もしあなたがそのルールを無視するか、あるいは部分的に無視する何らかのコレクションを実装しているなら(あなたが指定したケースのように)、あなたはCollectionインターフェイスの仕様を破ってしまいます。あなたが書いたとしても、「合格したコンパレータ**は、等しくなければなりません!!」 - 仕様は依然として破損したままです。 – bezmax

4

標準ライブラリにはこのような実装はありませんが、独自のものは使用できません。これは私がしばしば自分自身を持っていたかったものです。

は理由http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660を参照してください:

私たちは、複雑さを避けたかったです。コレクションのフレームワークが設計された時点で、この考えを真剣に受け入れましたが、それを拒否しました。 力量比は低くなっていたようです。私たちは等しいと感じました は時間の95%を望んでいました。 ==、4%;それ以外は1%。等価述語が と異なる場合、大量の操作のために合理的な 契約書を書くことは非常に難しいです。

関連する問題