关于Oracle中的示例';的java在线教程,该教程使用HashMap存储字谜
我正在阅读Oracle在线java教程中使用HashMap存储字谜的示例:关于Oracle中的示例';的java在线教程,该教程使用HashMap存储字谜,java,hashmap,hashtable,hashcode,anagram,Java,Hashmap,Hashtable,Hashcode,Anagram,我正在阅读Oracle在线java教程中使用HashMap存储字谜的示例: // Read words from file and put into a simulated multimap Map<String, List<String>> m = new HashMap<String, List<String>>(); try { Scanner s = new Scanner(new File(arg
// Read words from file and put into a simulated multimap
Map<String, List<String>> m = new HashMap<String, List<String>>();
try {
Scanner s = new Scanner(new File(args[0]));
while (s.hasNext()) {
String word = s.next();
String alpha = alphabetize(word);
List<String> l = m.get(alpha);
if (l == null)
m.put(alpha, l=new ArrayList<String>());
l.add(word);
}
} catch (IOException e) {
System.err.println(e);
System.exit(1);
}
// Print all permutation groups above size threshold
for (List<String> l : m.values())
if (l.size() >= minGroupSize)
System.out.println(l.size() + ": " + l);
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
//从文件中读取单词并放入模拟多重映射
Map m=新的HashMap();
试一试{
扫描器s=新扫描器(新文件(args[0]);
而(s.hasNext()){
字符串word=s.next();
字符串alpha=按字母顺序排列(单词);
列表l=m.get(α);
if(l==null)
m、 put(alpha,l=newarraylist());
l、 加(字);
}
}捕获(IOE异常){
系统错误println(e);
系统出口(1);
}
//打印大于大小阈值的所有置换组
对于(列表l:m.values())
如果(l.size()>=minGroupSize)
System.out.println(l.size()+“:”+l);
}
私有静态字符串字母顺序(字符串s){
char[]a=s.toCharArray();
数组。排序(a);
返回新字符串(a);
}
}
因为HashMap是用哈希表实现的,所以我认为每个按字母顺序排序的字符串在压缩后都应该有一个唯一的哈希代码(否则,在HashMap中存储值的链表将存储一个不是按字母顺序排序的字符串的字谜的值)
我不确定Java的HashMap实现如何满足这一点——我假设它们使用字符串的哈希代码(a1*31^n-1+a2*31^n-2+…+an)。如果我们讨论的字符串只有小写字符,那么这可能会保证哈希代码的唯一性。但是,在将bucket的键的值放入哈希表之前,还必须压缩哈希代码(否则,您将有一个无法在内存中处理的huggggge哈希表,只考虑31^10有多大)。在这种压缩中,我会认为会有碰撞。换句话说,两个不同的非真字谜字符串最终将存储在同一个存储桶中(该存储桶应仅用于存储真字谜列表)
有人能帮我理解我可能遗漏了什么吗?或者如果在线教程遗漏了什么
谢谢
Jason永远不要假设哈希代码是唯一的,但要意识到
HashMap
已经知道哈希代码是非唯一的,并适当地处理它们
换句话说,即使
a.hashCode()==b.hashCode()
,如果!a、 等于(b)
,那么aHashMap
将不会混淆与a
关联的值和与b
关联的值,特别是:感谢您将我指向该帖子。我可以理解哈希代码用于定位bucket,稍后将使用equals()方法检索正确的条目。但是,我无法想象在没有下一个节点指针的情况下如何在链表中存储多个节点。如果链表中有2+个节点没有下一个节点指针,那么链表就不再“链接”所有节点,因此不应该是链表,对吗?阅读了关于HashMap工作原理的说明后,另一个问题是,对于具有相同哈希代码的两个字符串(非字母表),java教程中提供的示例将它们存储在同一个bucket中。因此,您正在将类似“abc”、“cab”和“def”的内容保存到同一个链表中。虽然稍后您可能可以只打印“abc”和“cab”,但“def”存储在错误的位置,另一个预期该“def”的存储桶缺少字谜条目。不确定hashMap实现将如何解决此问题。或者这只是示例中的错误?我理解你评论的第一部分。但是,我不确定HashMap如何确保“如果!a.equals(b),那么HashMap将不会混淆与a关联的值和与b关联的值”。这正是我提出这个问题的原因。你能再解释一下吗?谢谢PHashMap
不仅查看键的哈希代码,它还检查键是否等于先前存在的键。因此,它不可能混淆a
和b
,因为它不仅检查hashCode
,还检查equals
。我认为HashMap在尝试从存储桶的链接列表hold中检索键/值时,只会使用equals方法检查键。您是说当我们将key/value放入HashMap时,实现也会使用equals方法检查key吗?我认为它只会使用HashCode(和抑制函数)来决定放哪个bucket条目。换句话说,如果两个字符串具有相同的哈希代码(并不意味着它们必须相等),那么它们将在同一个桶中结束。也许我错了?参考JDK1.6中HashMap的源代码(请参阅),我可以看到当我们试图获取条目时,它将调用equals方法。然而,当我们添加新条目时,实现会直接将新条目添加到链表的前面(并且不会调用任何equals检查)。