HashMap containsKey对相同字符串恒返回false,解析城市数据遇阻求助
这个问题我之前处理类似的文本解析时也碰到过!核心问题确实是字符串对象的实际内容不一致,导致Map的key匹配失败——毕竟String的equals和hashCode是基于字符序列的,只要两个字符串哪怕差一个空格、引号或者不可见字符,就会被当成不同的key。
咱们一步步来排查和解决:
1. 先搞定城市名的格式统一
你的输入里城市名有的带双引号(比如"San Antonio"),有的不带(比如Washington),这肯定会导致问题!比如你拆分后拿到的"San Francisco"和San Francisco是两个完全不同的字符串,Map.get自然找不到。
解决方法:解析每个城市名时,统一去除首尾的双引号,再清理多余空格:
// 去除首尾双引号,再trim掉前后可能的空格 String normalizeCity(String rawCity) { return rawCity.replaceAll("^\"|\"$", "").trim(); }
2. 清理隐藏的多余字符
有时候拆分字符串后,可能会引入看不见的字符(比如换行符、制表符),或者多个连续空格。这时候要做彻底的清理:
// 把所有空白字符(空格、换行、制表符等)替换成单个空格,再trim String normalizeCity(String rawCity) { return rawCity.replaceAll("^\"|\"$", "") .replaceAll("\\s+", " ") .trim(); }
3. 验证字符串一致性的调试技巧
如果还是有问题,一定要打印出key的真实状态,别光看表面:
// 打印带括号的key,方便看前后是否有隐藏空格 System.out.println("Key: [" + key + "]"); // 打印字符串长度,对比预期长度 System.out.println("Key length: " + key.length()); // 打印每个字符的ASCII码,排查隐藏字符 for (char c : key.toCharArray()) { System.out.println((int) c + " - " + c); }
比如如果某个Washington后面多了个换行符,长度就会比正常的长,ASCII码里能看到10(换行符的编码)。
4. 针对你的输入格式的解析示例
给你一段适配输入格式的解析代码,确保每一对城市和距离都被正确处理:
String input = "\"San Antonio\" \"San Francisco\" Washington \"San Francisco\"--Weed [305] \"San Francisco\"--\"Wisconsin Dells\" [2189] Washington--\"San Jose\" [2909]"; // 按距离条目拆分(比如"San Francisco"--Weed [305] 是一个完整条目) String[] entries = input.split("(?=(?:\"?\\w+\"?))"); for (String entry : entries) { entry = entry.trim(); if (entry.isEmpty()) continue; // 拆分城市对和距离部分 String[] parts = entry.split("\\s*\\[\\s*"); if (parts.length != 2) continue; // 提取距离 int distance = Integer.parseInt(parts[1].replaceAll("\\]", "").trim()); // 拆分两个城市 String[] cities = parts[0].split("\\s*--\\s*"); if (cities.length != 2) continue; // 标准化城市名 String city1 = normalizeCity(cities[0]); String city2 = normalizeCity(cities[1]); // 现在用city1和city2作为Map的key就不会有匹配问题了 System.out.println(city1 + " <-> " + city2 + ": " + distance); }
额外注意点
如果你不是用String作为Map的key,而是自定义的City类,那一定要正确重写equals()和hashCode()方法——只重写其中一个会导致更奇怪的问题,最好用IDE自动生成(比如IntelliJ的Generate -> equals() and hashCode()),基于城市名字段来生成。
按照这个思路处理,应该就能解决Map.get(key)返回null的问题了!
内容的提问来源于stack exchange,提问作者Slayahh




