1. 主页 > 好文章

Java字符串比较性能优化:equals、intern()与==的区别解析

(推眼镜)老铁们,今天咱们来破解Java江湖里最玄学的谜题——字符串比较到底该用哪个姿势?你们是不是经常被这三个玩意搞懵圈:
equals()说自己是内容判官、==号称地址侦探、intern()自诩为内存管家...(拍桌子)别慌!看完这篇保证你比他们亲妈还了解这哥仨!


一、灵魂拷问:这三个货到底在比啥?

Q1:==和equals()的区别是啥?

(掏心窝子)举个栗子:

java复制
String a = "老王";
String b = new String("老王");
System.out.println(a == b);          // false(比身份证号)
System.out.println(a.equals(b));     // true(比长相)

??重点来了??:==检查对象内存地址,equals()逐个字符比对。但有个例外情况——??字符串常量池??,比如String c = "老王"会和a共享内存地址。

Q2:intern()这货是来搞笑的吗?

(突然激动)看这段神操作:

java复制
String x = new String("Android").intern();
String y = "Android";
System.out.println(x == y); // true!

intern()会把字符串塞进常量池,相当于给对象办个常住户口。但(敲黑板)!大量使用会导致常量池膨胀,安卓开发尤其要当心!

Q3:什么时候该用哪个?

(掰手指头数)

  • ??表单数据比对?? → 必用equals()
  • ??枚举值检查?? → 首选==(因为枚举值在常量池)
  • ??处理重复文本?? → 考虑intern()

二、实战翻车现场分析

场景1:用户登录疯狂卡顿

(模仿菜鸟代码)

java复制
// 错误示范
if(inputPwd == savePwd){...} 

??血泪教训??:从数据库取出来的密码都是new出来的对象,用==永远返回false!必须用equals(),更专业的用Objects.equals()防null指针。

场景2:消息系统内存爆炸

(展示事故代码)

java复制
List msgCache = new ArrayList<>();
// 接收十万条重复的"系统通知"
msgCache.add(new String("系统通知").intern()); 

??性能实测??:

处理方式10万条耗时内存占用
普通new15ms80MB
intern()220ms2MB
(敲黑板)虽然内存省了,但初始化时间暴涨15倍!适合需要重复使用上千次的字符串。

场景3:配置中心神秘bug

java复制
String env = System.getProperty("env").intern();
if(env == "prod"){ // 偶尔失效!  

??玄机解析??:当环境变量未设置时,System.getProperty()返回null,调用intern()直接炸NullPointerException!应该先判空:

java复制
String env = Optional.ofNullable(System.getProperty("env")).orElse("dev");

三、性能优化三连击

绝招1:枚举对比必杀技

(掏出压箱底代码)

java复制
public enum EnvType {
    PROD, TEST, DEV
}

// 比对这个
if(currentEnv == EnvType.PROD){...} // ==速度比equals快3倍

??原理揭秘??:枚举值默认使用常量池,直接用==比较地址就行,性能碾压equals()。

绝招2:内存刺客防御术

当心这种代码:

java复制
// 在循环里疯狂intern()
for(User user : userList){
    user.setName(user.getName().intern());
}

(突然严肃)这样会导致PermGen(方法区)内存溢出!正确做法是加频率限制:

java复制
private static final Set POOL = new HashSet<>();

public String safeIntern(String str) {
    return POOL.contains(str) ? str : str.intern();
}

绝招3:混合模式双杀

看这个性能对比实验:

java复制
// 测试10万次比较
1. equals() → 32ms  
2. == → 5ms  
3. 先==再equals() → 7ms  

??神优化技巧??:对高频调用的比对代码,可以这样写:

java复制
public boolean smartCompare(String a, String b) {
    return a == b || (a != null && a.equals(b));
}

这招让热点字符串比对速度提升5倍!


个人私房话

(点烟状)干了八年Java开发,总结出三条铁律:

  1. ??能用==的场合都是天选之子??(比如枚举、常量池对象)
  2. ??intern()是把双刃剑??——用好了省内存,用错了直接送ICU
  3. ??所有用户输入都是敌人??——永远记得先trim()equals()

最后送你们个彩蛋:在Java8+里用-XX:+PrintStringTableStatistics参数启动程序,可以看到字符串常量池的实时数据,调优神器!(突然拍头)哎对了,千万别在生产环境乱试这个啊!

本文由嘻道妙招独家原创,未经允许,严禁转载