String.startsWith方法返回错误结果的问题排查
看起来你遇到的问题是String.startsWith()的匹配逻辑和预期不符——当传入字符串"14006"时,它会匹配到key为"1"的省份,但这显然不是你想要的结果,毕竟你应该是想匹配对应省份的完整编码前缀(比如西班牙省份的两位数字编码,14对应科尔多瓦)。
错误原因
startsWith()方法的逻辑是只要目标字符串以指定前缀开头就返回true,不管这个前缀的长度。所以"14006"确实以"1"开头,导致代码提前返回了这个短key对应的索引,而忽略了更长、更精确的前缀(比如"14")。
解决方案
根据你的需求,这里提供几种不同的解决思路,你可以根据实际情况选择:
1. 统一省份key的格式(最推荐)
西班牙的省份编码通常是两位数字,所以你可以把所有省份的key调整为两位格式——比如把"1"改成"01","2"改成"02",以此类推。这样一来,"14006"只会匹配key为"14"的项,不会再被"01"这类短key干扰。
这种方法从数据根源解决问题,后续的匹配逻辑不需要任何修改,简洁又可靠。
2. 优先匹配更长的key
如果无法修改现有数据,可以先将省份列表按key的长度降序排序,这样更长的、更精确的key会被优先遍历到。一旦匹配成功就返回,避免短key提前抢占匹配结果。
代码示例:
public int getIndexIfStartsWith(String str){ // 创建原列表的副本,避免修改原数据 List<Province> sortedModels = new ArrayList<>(models); // 按key长度从长到短排序 sortedModels.sort((p1, p2) -> Integer.compare(p2.getKey().length(), p1.getKey().length())); for(Province province : sortedModels){ String key = province.getKey(); if(str.startsWith(key)){ // 返回该省份在原列表中的索引 return models.indexOf(province); } } return -1; }
注意:如果你的
models列表中有重复的Province对象,indexOf()会返回第一个匹配项的索引,需要根据你的业务场景调整。
3. 精确匹配指定长度的前缀
如果你明确知道省份编码的长度(比如两位),可以直接判断字符串的前N位是否等于key,而不是用startsWith():
代码示例:
public int getIndexIfStartsWith(String str){ // 确保传入的字符串长度足够(至少两位) if(str.length() < 2){ return -1; } String prefix = str.substring(0, 2); for(int index = 0; index < models.size(); index++){ String key = models.get(index).getKey(); // 只匹配长度为2的key,且与前缀完全相等 if(key.length() == 2 && key.equals(prefix)){ return index; } } return -1; }
这种方式逻辑最直接,适合你对省份编码长度有明确要求的场景。
内容的提问来源于stack exchange,提问作者Víctor Martín

