两个内容看似相同的Java ArrayList为何equals比较返回false?
排查Java字符串equals返回false的常见原因
这种情况我之前排查过好多次,肉眼看着完全一致的字符串,equals()却返回false,在你已经排除普通空格的情况下,大概率是不可见字符或编码差异在作祟,给你列几个最常见的原因和排查方法:
1. 隐藏的不可见空白字符
这是最常见的问题!很多Unicode空白字符肉眼根本分辨不出来,比如:
- 全角空格(U+3000):看起来和半角空格一样,但编码完全不同
- 非断空格(U+00A0):常见于网页或某些数据库导出的文本
- 零宽空格(U+200B):完全看不见,却会占字符位置
- 制表符(\t)、换行符(\n)、回车符(\r):有时候打印时会被忽略,但实际存在于字符串中
2. 字符串首尾的控制字符
比如空字符(\0)、Unicode控制字符(U+0000到U+001F之间的字符),这些字符在控制台输出时不会显示,但会直接影响equals()的判断。
3. 编码不一致导致的字符差异
从不同数据库加载数据时,如果两个数据库的字符编码设置不同(比如一个用GBK,一个用UTF-8),某些特殊字符可能会被解析成不同的Unicode码点,看起来一样但实际编码不同。
快速排查方法
方法一:逐个字符打印Unicode编码
写个简单的循环,对比两个字符串每个字符的编码值,一目了然:
String str1 = list1.get(1); String str2 = list2.get(1); // 遍历每个字符,输出字符和对应的Unicode码 for (int i = 0; i < Math.max(str1.length(), str2.length()); i++) { char c1 = i < str1.length() ? str1.charAt(i) : ' '; char c2 = i < str2.length() ? str2.charAt(i) : ' '; System.out.printf("位置 %d: str1='%c' (编码: %d), str2='%c' (编码: %d)%n", i, c1, (int)c1, c2, (int)c2); }
如果某个位置的编码值不一样,那就是问题所在。
方法二:清除所有不可见字符后再比较
用正则表达式去掉所有Unicode控制字符和空白字符,再看是否相等:
String cleanedStr1 = str1.replaceAll("\\p{C}", "").replaceAll("\\p{Z}", ""); String cleanedStr2 = str2.replaceAll("\\p{C}", "").replaceAll("\\p{Z}", ""); System.out.println(cleanedStr1.equals(cleanedStr2));
如果返回true,说明原字符串里确实有不可见字符。
内容的提问来源于stack exchange,提问作者EdXX
相关产品推荐
相关产品推荐

