哈希表精确值查找问题:拼写检查程序匹配异常如何解决
问题根因
你当前遇到的匹配异常问题核心是3个错误导致的:
- String类是不可变类型,你写的
p.trim()不会修改原字符串内容,等于没执行修剪操作,用户输入的前后残留空格会导致匹配异常 - 存、查两侧大小写不统一:构建哈希表时直接存储了文件读取的原始大小写单词,但查询时把用户输入转成了全大写,
equals对比是区分大小写的,会出现预期外的匹配/不匹配结果 - 哈希表用法错误:你用自增整数作为键、单词作为值,
containsValue方法需要遍历全表逐个对比,不仅性能是O(n),也不符合哈希表的设计用途,也会增加匹配逻辑出问题的概率
另外你描述的「只要匹配到值中存在连续的对应两个字母就判定输入有效」不符合你贴出代码的逻辑——JDK自带的Hashtable.containsValue底层是调用String.equals做完全匹配,不会做子串匹配,出现这个问题大概率是你的words.txt文件本身就存在和短输入完全一致的单词,或者你实际运行的代码私自修改了匹配逻辑用了contains子串匹配方法。
修复方案
1. 调整哈希表存储逻辑
把哈希表的键改为单词,利用哈希表O(1)按键查询的特性,同时存储时统一转大写:
// 哈希表声明修改 Hashtable<String, Boolean> hash = new Hashtable<>(); String input; ArrayList<String> toReturn = new ArrayList<>(); String line; File allTheWords = new File("words.txt"); public void createTable() throws IOException { Scanner rd = new Scanner(allTheWords); while (rd.hasNextLine()) { line = rd.nextLine(); // 修剪+统一转大写后存为键 String word = line.trim().toUpperCase(); hash.put(word, true); } rd.close(); if (hash.isEmpty()) { System.out.println("Sorry. The function did not work"); } if (hash.size() > 0) { // 随机取单词的逻辑微调 List<String> keys = new ArrayList<>(hash.keySet()); Random random = new Random(); int randomIndex = random.nextInt(keys.size()); System.out.println("Success! You created a hashtable!"); String randomWord = keys.get(randomIndex); System.out.println("For example, the random word is " + randomWord); } }
2. 修正查询逻辑
public void run() { Scanner userIn = new Scanner(System.in); System.out.print("\n---Enter a word to check the spelling: "); String s = userIn.nextLine(); // 修剪+转大写,必须赋值给变量才会生效 String p = s.trim().toUpperCase(); // 按键查询,默认完全匹配 if (hash.containsKey(p)) { System.out.println("\n" + p + " is spelled correctly"); } else { System.out.println("Apologies. That word is not found"); // 后续要做的字母错位、遗漏识别逻辑可以放在这里 // 遍历所有键计算和p的编辑距离,返回编辑距离≤2的单词作为建议即可 } userIn.close(); System.out.println(p); }
3. 兜底排查
如果修改完成后还是出现子串匹配的问题,直接检查你的words.txt文件,确认是否本身就存在对应短输入的单词(比如确实有"TE"这个缩写词),上述修复后的匹配逻辑是100%完全字符串匹配,不会出现子串匹配的情况。
内容的提问来源于stack exchange,提问作者1chick
相关产品推荐
相关产品推荐

