Dav*_*veM 0 java dictionary hashcode treemap compareto
我在另一个TreeMap中使用TreeMap作为"键"
即
TreeMap<TreeMap<String, String>, Object>
Run Code Online (Sandbox Code Playgroud)
在我的代码中,'object'是一个个人构造,但是对于这种情况,我使用了一个字符串.
我创建了一对TreeMaps来测试TreeMap.CompareTo()和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");
Run Code Online (Sandbox Code Playgroud)
从这里我现在调用英语项目来查看它是否包含密钥
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?
}
Run Code Online (Sandbox Code Playgroud)
但是我应该注意,HashMap和TreeMap都指向AbstractMap父级中的相同HashCode()方法.
我的第一个想法是将我的TreeMap转换为HashMap,但这看起来有点过时了!所以我决定将hashCode()方法应用于2个treemap对象.
int hc1 = first.hashCode();
int hc2 = second.hashCode();
if(hc1 == hc2)
{
systom.out.printline("values are equal " + hc1 + " " + hc2);
}
Run Code Online (Sandbox Code Playgroud)
打印以下内容
values are equal 3877431 & 3877431
Run Code Online (Sandbox Code Playgroud)
对我来说,哈希码应该是不同的,因为键值不同,我找不到HashMap和TreeMap之间hashCode()方法的实现差异的细节.
请不要以下.仅将Keys更改为HashMap不会停止ClassCastException错误.将所有映射更改为HashMap可以.所以TreeMap中的containsKey()方法有些不能正常工作,或者我误解了 - 有人可以解释一下吗?
我得到第一个和第二个映射对象的hashCode的部分总是产生相同的输出(无论我在这里使用Hash或Tree映射)但是if(english.ContainsKey(second))在不打印任何消息时使用了HashMaps,因此HashMap实现中显然有一些与compareTo()方法不同的东西.
我的主要问题是.
我在哪里可以找到在TreeMap对象中使用的键类型的详细信息(以防止将来出现'ClassCastException'错误).
如果我不能使用某种类型的对象作为键,为什么我可以首先将它作为键插入到TreeMap中?(当然,如果我可以插入它,我应该能够检查密钥是否存在?)
任何人都可以建议另一个命令inster/retrieval来替换我的TreeMap关键对象吗?
或者我有可能发现奇怪的行为.根据我的理解,我应该能够为HashMap替换TreeMap,或者我偶然发现了一个边缘场景?
提前感谢您的意见.
大卫.
PS.问题不是我的代码中的问题,因为我使用个人实用程序来创建一个依赖于键和值对的哈希(即我计算键值哈希值与值哈希值不同...对不起,如果是一个令人困惑的句子!)我假设hashCode方法只是将所有值加在一起而不考虑项是键还是值.
PPS.我不确定这是不是一个好问题,关于如何改进它的任何指示?
编辑.
从回答中人们似乎认为我正在做一些奇特的语言词典,不是我的例子中的惊喜,所以很抱歉.我用这个作为一个例子,因为它很容易出现在我的大脑中,很快写作并展示了我的问题.
真正的问题如下.
我正在访问一个遗留的数据库结构,它不能很好地与任何东西交谈(结果集不是正向和反向可读等).所以我抓住数据并从中创建对象.最小的对象表示表中的单个行(这是在上面的示例中我使用字符串值'english'或'french'的对象.
我有一些这些rowObject的集合,每一行都有一个明显的键(这是指向相关rowObject的TreeMap).
我不知道这是否让事情更清楚!
编辑2.
我觉得我需要进一步阐述我对原始使用的选择
hashMap<HashMap<String,string>, dataObject>
Run Code Online (Sandbox Code Playgroud)
对于我的数据结构,然后转换为TreeMap以获得有序视图.
在编辑1中,我说遗留数据库不能很好地发挥作用(这是我怀疑的JDBC.ODBC的一个问题,而且我不打算获取JDBC来与数据库通信).事实是我对数据应用了一些修改,就像我创建java'dataObject'一样.这意味着尽管DB可能会按升序或降序吐出结果,但我无法知道它们插入到dataObject中的顺序.使用likesHashMap似乎是一个很好的解决方案(请参阅duffymo的建议),但后来我需要以有序的方式提取数据,而不仅仅是连续提取(LinkedHashMap只保留插入顺序),而且我不会痴迷于订购所有内容和当我需要在2个其他人之间插入一个新项目时,TreMap会为我做这个...但是如果我为这个键创建一个特定的对象,它将只包含一个TreeMap作为成员,显然我将需要提供compareTo和hashCode方法.那么为什么不只是范围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);
}
}
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您似乎想要将英语单词翻译为法语,然后查看法语词典是否包含该单词:
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);
Run Code Online (Sandbox Code Playgroud)