我正在阅读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(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);
}
}
由于HashMap是用哈希表实现的,我认为每个按字母顺序排序的字符串在压缩后都应该有一个唯一的哈希代码(否则,存储HashMap中值的链表将存储一个不是按字母顺序排列的字符串的变位符的值)。
我不太确定Java的HashMap实现如何满足这一点——我假设它们使用字符串的哈希代码(a1*31^n-1+a2*31^n-2+…+an)。如果我们谈论的是只有小写字符的字符串,这可能会保证哈希代码的唯一性。然而,在将bucket的键的值放入哈希表之前,还必须压缩哈希代码(否则,你会有一个无法在内存中处理的huggggge哈希表,只考虑31^10有多大)。在这种压缩中,我认为会有碰撞。换言之,两个不同的非真变位符字符串最终将存储在同一个存储桶中(该存储桶应仅用于存储真变位符号列表)。。。
有人能帮我了解一下我可能遗漏了什么吗?或者如果在线教程遗漏了什么?
谢谢!
Jason
永远不要假设哈希码是唯一的——但要意识到HashMap
已经知道哈希码是非唯一的,并适当地处理它们。
换句话说,即使是a.hashCode() == b.hashCode()
,如果是!a.equals(b)
,则HashMap
也不会混淆与a
相关联的值和与b
相关联的数值。