0

TreeMap を別の TreeMap 内の「キー」として使用します

すなわち

TreeMap<TreeMap<String, String>, Object>

私のコードでは、「オブジェクト」は個人的な構造ですが、この例では文字列を使用しています。

TreeMap.CompareTo()メソッドとメソッドをテストするために、TreeMap のペアを作成しましたTreeMap.HashCode()。これは次から始まります...

public class TreeMapTest 

public void testTreeMap()
{
TreeMap<String, String> first = new TreeMap<String, String>();
TreeMap<String, String> second = new TreeMap<String, String>();

first.put("one", "une");
first.put("two", "deux");
first.put("three", "trois");
second.put("une", "one");
second.put("deux", "two");
second.put("trois", "three");

TreeMap<TreeMap<String, String>, String> english = new TreeMap<TreeMap<String, String>, String>();
TreeMap<TreeMap<String, String>, String> french = new TreeMap<TreeMap<String, String>, String>();

english.put(first, "english");
french.put(second, "french");

ここから英語のアイテムを呼び出して、キーが含まれているかどうかを確認します

if (english.containsKey(second))
{
System.out.println("english contains the key");
//throws error of ClassCastException: Java.util.TreeMap cannot be cast to
//Java.Lang.Comparable, reading the docs suggests this is the feature if the key is
//not of a supported type.
//this error does not occur if I use a HashMap structure for all maps, why is
//this key type supported for one map structure but not another?
}

ただし、HashMap と TreeMap の両方が AbstractMap 親の同じ HashCode() メソッドを指していることに注意してください。

私が最初に考えたのは、TreeMap を HashMap に変換することでしたが、これは少し面倒に思えました。そこで、hashCode() メソッドを 2 つのツリーマップ オブジェクトに適用することにしました。

int hc1 = first.hashCode();
int hc2 = second.hashCode();



if(hc1 == hc2)
{
systom.out.printline("values are equal " + hc1 + " " + hc2);
}

以下を印刷します

values are equal 3877431 & 3877431

私にとっては、キー値が異なるため、ハッシュコードは異なるはずです。HashMap と TreeMap の間の hashCode() メソッドの実装の違いに関する詳細を見つけることができません。

以下の方はご遠慮ください。キーのみを HashMap に変更しても、ClassCastException エラーは停止しません。すべてのマップを HashMap に変更します。TreeMap の containsKey() メソッドに何か問題があり、それが正しく機能していないか、私が誤解しています - 誰か説明してもらえますか?

最初と 2 番目のマップ オブジェクトの hashCode を取得するセクションでは、常に同じ出力が生成されます (ここでハッシュまたはツリー マップを使用するかどうかに関係なく)。 HashMaps が使用されるため、compareTo() メソッドとは異なる HashMap 実装に明らかに何かがあります。

私の主な質問は次のとおりです。

TreeMap オブジェクトで使用するキーの種類の詳細はどこで確認できますか (将来の 'ClassCastException' エラーを防ぐため)。

特定のタイプのオブジェクトをキーとして使用できない場合、そもそもそれをキーとして TreeMap に挿入できるのはなぜですか? (確かに挿入できれば、キーが存在するかどうかを確認できるはずですか?)

私の TreeMap キーオブジェクトを置き換えるために inster/retrieve を注文した別の構造を誰かが提案できますか?

または、奇妙な動作を発見した可能性があります。私の理解では、HashMap の代わりに TreeMap をドロップインできるはずですか、それともフリンジ シナリオに出くわしましたか?

コメントありがとうございます。

デビッド。

ps。個人用ユーティリティを使用して、キーと値のペアに依存するハッシュを作成するため、問題は私のコードの問題ではありません (つまり、キー ハッシュ値を値ハッシュ値とは異なる方法で計算します...混乱を招く場合は申し訳ありません文!) hashCode メソッドは、項目がキーであるか値であるかを考慮せずに、すべての値を合計するだけであると想定しています。

pps。これが良い質問かどうかわかりませんが、それを改善する方法についての指針はありますか?

編集。

応答から、人々は私がある種の派手な言語辞書のことをしていると思っているようですが、私の例からの驚きではありません。私はこれを例として使用しました。なぜなら、それは私の頭に簡単に浮かび、書くのが速く、私の質問を実証したからです.

本当の問題は次のとおりです。

私は従来の DB 構造にアクセスしていますが、何ともうまく通信しません (結果セットが前方および後方読み取り可能でないなど)。そこで、データを取得して、そこからオブジェクトを作成します。最小のオブジェクトは、テーブル内の 1 つの行を表します (これは、上記の例で文字列値 'english' または 'french' を使用したオブジェクトです。

これらの行オブジェクトのコレクションがあり、各行には明らかなキーがあります (これは、関連する行オブジェクトを指す TreeMap です)。

それが物事をより明確にするかどうかはわかりません!

2を編集します。

オリジナルの使用方法の選択について、もう少し詳しく説明する必要があると感じています

hashMap<HashMap<String,string>, dataObject>

私のデータ構造の場合、TreeMap に変換して順序付けられたビューを取得します。

編集 1 で、レガシー DB はうまく動作しないと言いました (これは JDBC.ODBC の問題であると思われます。DB と通信するために JDBC を取得するつもりはありません)。真実は、Java「dataObject」を作成するときに、データにいくつかの変更を適用することです。つまり、DB は結果を昇順または降順で吐き出す可能性がありますが、dataObject に挿入された順序を知る方法はありません。likeHashMap を使用することは良い解決策のように思えますが (duffymo の提案を参照)、後でデータを連続的にではなく、順序付けられた方法で抽出する必要があります (LinkedHashMap は挿入順序のみを保持します)。他の 2 つのアイテムの間に新しいアイテムを挿入する必要があるときにコピーを作成する場合、TreMap がこれを行います... しかし、キーの特定のオブジェクトを作成すると、メンバーとして TreeMap が含まれるだけになるため、compareTo メソッドと hashCode メソッドを指定する必要があることは明らかです。では、TreeMap をエクステントするだけではどうですか (ただし、Duffymo はそのソリューションを破棄することにポイントがあります)。

4

3 に答える 3

6

これは良い考えではありません。マップ キーは、適切に機能するために不変でなければなりませんが、あなたのキーはそうではありません。

あなたは本当に何をしようとしていますか?データ構造でこのようなことをしている人を見ると、本当にオブジェクトが必要なのに、Java がオブジェクト指向言語であることを忘れているのだと思います。

粗雑な辞書を言語間で翻訳したいようです。これらのマップを埋め込んだクラスを作成し、LanguageLookupユーザーが操作しやすいようにいくつかのメソッドを提供します。より良い抽象化とカプセル化、より多くの情報隠蔽。これらを設計目標にする必要があります。他のコンテキストで使用できるように、英語とフランス語以外の言語を追加する方法を考えてください。

public class LanguageLookup { 
    private Map<String, String> dictionary;

    public LanguageLookup(Map<String, String> words) {
        this.dictionary = ((words == null) ? new HashMap<String, String>() : new HashMap<String, String>(words));
    }

    public String lookup(String from) {
        return this.dictionary.get(from);
    }

    public boolean hasWord(String word) { 
        return this.dictionary.containsKey(word);
    }
}

あなたの場合、英語の単語をフランス語に翻訳し、フランス語の辞書にその単語が含まれているかどうかを確認したいようです:

Map<String, String> englishToFrenchWords = new HashMap<String, String>();
englishToFrenchWords.put("one", "une");
Map<String, String> frenchToEnglishWords = new HashMap<String, String>();
frenchToEnglishWords.put("une", "one");
LanguageLookup englishToFrench = new LanguageLookup(englishToFrenchWords);
LanguageLookup frenchToEnglish = new LanguageLookup(frenchToEnglishWords);
String french = englishToFrench.lookup("one");
boolean hasUne = frenchToEnglish.hasWord(french);
于 2012-07-10T11:37:40.150 に答える
2

TreeMap は Comparable ではないため、SortedMap に追加できず、不変ではないため、HashMap に追加できません。IdentityMap を使用できるが、EnumMap の方が適していると思われるもの。

enum Language { ENGLISH, FRENCH }

Map<Language, Map<Language, Map<String, String>>> dictionaries = 
                                                    new EnumMap<>(Language.class);

Map<Language, Map<String, String>> fromEnglishMap = new EnumMap<>(Language.class);
dictionaries.put(Language.ENGLISH, fromEnglishMap);
fromEnglishMap.put(Language.FRENCH, first);

Map<Language, Map<String, String>> fromFrenchMap = new EnumMap<>(Language.class);
dictionaries.put(Language.FRENCH, fromFrenchMap);
fromEnglishMap.put(Language.ENGLISH, second);

Map<String, String> fromEnglishToFrench= dictionaries.get(Language.ENGLISH)
                                             .get(Language.FRENCH);
于 2012-07-10T11:57:18.940 に答える
0

Hashmap が機能し、Treemap が機能しない理由については、次のとおりです。

Treemap は「ソートされたマップ」です。つまり、エントリはキーに従ってソートされます。これは、Comparableインターフェイスを実装することによって、キーが比較可能でなければならないことを意味します。通常、マップはこれを実装していません。この機能を追加するためにカスタム タイプを作成しないことを強くお勧めします。ダフィモが言及しているように、マップをキーとして使用するのは悪い考えです。

于 2012-07-10T11:46:07.307 に答える