Java 比较树映射内容给出了不正确的答案

Java 比较树映射内容给出了不正确的答案,java,dictionary,hashcode,treemap,compareto,Java,Dictionary,Hashcode,Treemap,Compareto,我使用一个树状图作为另一个树状图中的“键” 即 从这里,我现在调用英语项,看看它是否包含键 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 sugges

我使用一个树状图作为另一个树状图中的“键”

从这里,我现在调用英语项,看看它是否包含键

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()方法

我的第一个想法是将我的树状图转换为哈希图,但这似乎有点令人毛骨悚然!因此,我决定将hashCode()方法应用于2个treemap对象

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



if(hc1 == hc2)
{
systom.out.printline("values are equal " + hc1 + " " + hc2);
}
打印以下内容

values are equal 3877431 & 3877431
对我来说,hashcode应该是不同的,因为键值不同,我找不到HashMap和TreeMap之间hashcode()方法实现差异的详细信息

请不要写下面的内容。 仅将键更改为HashMap不会停止ClassCastException错误。将所有映射更改为HashMap不起作用。因此,TreeMap中containsKey()方法有一些地方工作不正常,或者我理解错误——有人能解释一下吗

我获取第一个和第二个映射对象的hashCode的部分总是产生相同的输出(无论我在这里使用的是Hash映射还是树映射),但是if(english.ContainsKey(second))在使用HashMap时不会打印任何消息,因此HashMap实现中显然存在与compareTo()不同的东西方法

我的主要问题是

在哪里可以找到树映射对象中使用的键类型的详细信息(以防止将来出现“ClassCastException”错误)

如果我不能使用某种类型的对象作为键,为什么首先允许我将其作为键插入树映射?(当然,如果我可以插入它,我应该能够检查密钥是否存在?)

有人能推荐另一个命令inster/retrieval替换我的树映射键对象的构造吗

或者我可能发现了奇怪的行为。根据我的理解,我应该能够用树形图替换HashMap,或者我偶然发现了一个边缘场景

提前感谢您的评论

大卫

另外,这个问题在我的代码中不是问题,因为我使用个人实用程序创建了一个依赖于键和值对的散列(即,我计算键散列值的方式不同于值散列值……很抱歉,if是一个令人困惑的句子!)我假设hashCode方法只是将所有值相加,而不考虑项是键还是值

pps。我不确定这是不是一个好问题,有没有关于如何改进的建议

编辑

从回答来看,人们似乎认为我在做一些花哨的语言词典的东西,从我的例子来看,这并不奇怪,所以对此感到抱歉。我用它作为一个例子,因为它很容易进入我的大脑,很快就写出并演示了我的问题

真正的问题如下

我正在访问一个遗留的数据库结构,它与任何东西都不能很好地对话(结果集不能向前和向后读取等等)。所以我获取数据并从中创建对象。 最小的对象表示表中的一行(在上面的示例中,我使用字符串值'english'或'french'表示该对象)

我有这些rowObject的集合,每一行都有一个明显的键(这是指向相关rowObject的树状图)

我不知道这是否能让事情变得更清楚

编辑2

我觉得我需要进一步详细说明我对最初使用的选择

hashMap<HashMap<String,string>, dataObject>
hashMap
对于我的数据结构,然后转换为TreeMap以获得有序视图

在edit1中,我说遗留数据库不能很好地发挥作用(我怀疑这是JDBC.ODBC的问题,我不打算购买JDBC来与数据库通信)。事实上,我在创建java“dataObject”时对数据进行了一些修改。这意味着,尽管DB可能会按升序或降序输出结果,但我无法知道它们插入数据对象的顺序。使用likedHashMap似乎是一个不错的解决方案(见duffymo的建议)但我以后需要以有序的方式提取数据,而不仅仅是连续提取(LinkedHashMap只保留插入顺序),当我需要在另外两个项之间插入一个新项时,我不想乱排序和复制,TreMap会帮我这么做……但是如果我为键创建一个特定的对象,它只会包含一个树形图作为成员,显然我需要提供一个compareTo和hashCode方法。那么为什么不直接使用e呢xtent TreeMap(尽管Duffymo有一点要放弃该解决方案)!

这不是一个好主意。映射键必须是不可变的才能正常工作,而您的映射键则不是

你到底想做什么?当我看到人们用数据结构做这样的事情时,我觉得他们真的需要一个对象,但却忘记了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);
    }
}
公共类语言查找{
专用地图词典;
公共语言查找(映射词){
this.dictionary=((words==null)?new HashMap():new HashMap(words));
}
公共字符串查找(字符串来自){
返回此.dictionary.get(from);
}
公共布尔字(字符串字){
返回此.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);
Map englishToFrenchWords=newhashmap();
英语
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);
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);