今天在做字符串比较时遇到个很新奇的问题,在此记录一下。
字符串比较最常用的方法就是equals方法,来看一下下面这个比较会返回什么结果呢?
public static void main(String[] args) {
{
String s1 = "⽹"; // 12153
String s2 = "网"; // 32593
boolean result = s1.equals(s2);
System.out.println(result);
}
{
String s1 = "⽺"; // 12154
String s2 = "羊"; // 32650
boolean result = s1.equals(s2);
System.out.println(result);
}
}
你第一眼看到这段代码可能会想 “这作者该不会是个傻子吧?”,😂
但是,两个result结果又确实都是false。
Java的String对象中char字符的编码格式为UTF-16。debug看一下这几个字的UTF-16的值
看看,看着长的一样的字,UTF-16的值却不同,确实不是同一个字符吧
这是什么情况呢?网上搜了一通,大概是什么“兼容表意文字区”与“统一表意文字区”的区别,我对文字编码了解不深,感兴趣的自己去研究吧。
那产品经理看到该说了:“这两个字明明长的一样,你总不能告诉用户说这俩字不是同一个字吧?你用技术手段处理下,让他们做比较时认为是同一个字”
我说:“xxxxxxxxx……没问题”,只不过需要一个方法来将字符串提前处理一下,这个方法是jdk自带的:
这是加上转换的代码
public static void main(String[] args) {
{
String s1 = "⽹"; // 12153
String s2 = "网"; // 32593
s1 = Normalizer.normalize(s1,Normalizer.Form.NFC);
s2 = Normalizer.normalize(s2,Normalizer.Form.NFC);
boolean result = s1.equals(s2);
System.out.println(result);
}
{
String s1 = "⽺"; // 12154
String s2 = "羊"; // 32650
s1 = Normalizer.normalize(s1,Normalizer.Form.NFC);
s2 = Normalizer.normalize(s2,Normalizer.Form.NFC);
boolean result = s1.equals(s2);
System.out.println(result);
}
}
debug一下看看转换后的结果
转换了一道后,值一样了,再次使用 equals 就返回 true 了,大功告成。