2012-04-14 6 views
4

私はC++の経験が少しあるJavaのnoobです。次のような行に沿ってJavaのセットを作成しようとしています。Javaジェネリックとセットのセット

Set< Set<String> > collection = new TreeSet< Set<String> >(); 
Set<String> entry = new TreeSet<String>(); 
collection.add(entry); 

これは正常に構築されますが、プログラムの実行時にjava.util.TreeSet cannot be cast to java.lang.Comparable例外がスローされます。

ホイールを再実装することなく、Javaのセットをどのように設定できますか?

また、壊れたコード(型の不一致など)をコンパイルできるJavaとの取り引きは何ですか?

フィードバックをいただきありがとうございます。 TreeSetの契約で

+0

私はこの特定のケースでHashSetを使用したいと思います(問題については、biziclopの説明を参照してください)。 – Raveline

+0

アウターセットはソートセットにする必要がありますか?そうであれば、ソートルールは何ですか? – nansen

+0

注文は関係ありません。私は問題を説明するためにTreeSetを使用しました。私の推測では、HashSetも同様です(ただし、処理されたデータについて十分な知識がない場合は、ヒューリスティック(つまり、ハッシュ関数)に依存するアルゴリズムはほとんど気になりません)。 – Meh

答えて

6

、要件は、すべてのエントリがComparableでなければならないか、Comparatorを提供する必要があることにレイアウトされます。それは、ジェネリック医薬品とは何の関係も持っていないです

、それはTreeSetの実装から来る:(エントリは明示的なComparatorが存在しない場合にComparableにキャストされている。これは、コンパイル時エラーを見ていない理由もあります)それ自体はバイナリツリーなので、何らかの順序でエントリを並べ替えることができます。

具体的な問題についてもう少し詳しくお知りになりたい場合は、必要なデータ構造を正確に見つけることができますが、一般的には、要素の順序を気にしない場合はHashSetが使用されます。また、一般に、SetSetであることは、しばしばデザインが荒いことを示しています。

+0

チップをありがとう。私はおそらくカスタムコンパレータを実装するでしょう。 – Meh

+0

特定の問題は、実際には上記のサンプル問題と同じくらい簡単です。私は文字列トークンのユニークなセットを追跡し、それらを印刷する必要があります。だから、非常に単純な問題であり、あらゆる種類のラッパークラスを書くことはそれを過度に行っていたと思います。デザインについては、よく、私はまだそれを足に自分自身を撃つオプションがあります:) – Meh

+0

@Mehその後、あなたのケースは、セットのセットを使用すると1%で正当化されます。 :) – biziclop

2

TreeSetコレクションにオブジェクトを追加する場合、そのオブジェクトのタイプはComparableインターフェイスを実装する必要があります。TreeSet自体はそうではありません。また、別のコンストラクタを使用してTreeSetを作成してComparatorを指定することもできます。

このシナリオではTreeSetを使用するのは実際には意味がありません。これは、定義上、順序付けされたコレクションであり、要素の順序付けを必要としないためです。代わりにHashSetを試すことができます。あなたが実際に実行時にTreeSetにバインドされているSetに追加されている多型の挙動、すなわちを利用しているため

はまた、あなたの2番目の質問に答えるために、このエラーは、実行時にのみ表示されます。この情報はコンパイル時には分かりません。

+0

明示的コンパレータを提供することもできるので、100%正確ではありません。 – biziclop

+0

@biziclop:ありがとう、私は完全性のためにその情報を追加しました。 – Tudor

0

TreeSetは、カスタムコンパレータまたはのいずれかを受け入れることができる必要があるため、ジェネリックスの観点から完全に「型保証」ではありません。

TreeSetが自然順序付けのみを使用した場合は、TreeSet<E extends Comparable<? super E>>と宣言でき、タイプセーフなものになります。それ自体に匹敵しない型はパラメータとして使用できません。一方、常にコンパレータを使用する場合は、タイプセーフでもあります。

しかし、今設計されている方法では、比較器を持たないTreeSetを作成することができます(したがって、自然順序付けを使用することができます)。これを強制するコンパイル時チェックはありません。障害は実行時にのみ通知されます。

TreeSetを固定することができる方法が実際にあります。それは自然の秩序とカスタムコンパレータの両方をサポートし、タイプセーフになります

  • は、カスタムコンパレータに

  • を受け取るコンストラクタは自然順序付けケースにはコンストラクタを持っていませんでした。代わりに、自然順序付けを使用するTreeSetを作成するファクトリメソッドを用意してください。ファクトリメソッドは、Javaライブラリの設計者は、このようにそれをしなかった理由を私は知らない

自体に匹敵するタイプを必要と<E extends Comparable<? super E>>をバインドジェネリック型を持つことができます。