0

0

详解String.intern()与集合去重_如何在集合中节省重复字符串内存

P粉602998670

P粉602998670

发布时间:2026-02-11 14:07:34

|

913人浏览过

|

来源于php中文网

原创

String.intern() 不总能省内存,仅在动态生成的高重复字符串场景下有效,但有GC压力、哈希冲突和锁开销;多数场景推荐用HashSet等集合去重,更可控、安全。

详解string.intern()与集合去重_如何在集合中节省重复字符串内存

String.intern() 真的能帮你省内存吗?

不能一概而论。它只在字符串内容重复率高、且这些字符串由 new String() 或非字面量方式构造时,才可能节省堆内存;但会把字符串引用转移到常量池(JDK 7+ 是堆内元空间/字符串表),带来 GC 压力和哈希冲突风险。

常见错误现象:OutOfMemoryError: Metaspace(JDK 8)或 GC 频繁(JDK 7+ 堆内字符串表膨胀);intern() 后的字符串比较用 == 仍返回 false(比如和字面量混用但没注意加载顺序)。

  • 只对运行期动态拼接、解析生成的重复字符串有效,比如 JSON 解析出的字段名、日志中的固定状态码
  • 字面量字符串(如 "OK")本身就在常量池,再调 intern() 是空操作
  • intern() 是 native 方法,有锁开销,高并发下调用需权衡
  • JDK 7 之前 intern 到永久代,极易 OOM;JDK 7+ 默认在堆,但需通过 -XX:StringTableSize 调优,默认仅 60013 桶,冲突多时查找变慢

用 Set 去重比 intern() 更稳当?

是的,绝大多数场景下更推荐。集合去重逻辑清晰、可控、无隐式内存迁移,适合业务层统一管理重复字符串生命周期。

使用场景:读取大量 CSV/JSON 数据做 dedup,缓存 key 归一化,用户输入标签清洗等。

  • HashSet 依赖 String.hashCode()equals(),不依赖 JVM 内部字符串表
  • 若需保留插入顺序,选 LinkedHashSet;若后续要排序,直接上 TreeSet(但注意 String 自然序可能不符合业务语义)
  • 注意:HashSet 的初始容量别设太小,否则扩容 + rehash 成本高;预估重复率高时,可设大些,比如 new HashSet(10000, 0.75f)
  • 不要为了“省一个对象”在循环里反复 set.add(str.intern())——这既没省堆内存(intern() 返回的是常量池引用,原对象还在),又白耗 CPU

StringTableSize 不调,intern() 就像抽奖

默认 StringTableSize=60013,是个质数,但如果你有 10 万个高频重复字符串要 intern,哈希桶严重不足,链表退化成线性查找,性能断崖下跌。

Flowith
Flowith

一款GPT4驱动的节点式 AI 创作工具

下载

错误现象:intern() 耗时从纳秒级升到微秒甚至毫秒级;jstack 看到多个线程卡在 StringTable::intern 的 synchronized 块里。

  • 估算峰值唯一字符串数,设为 -XX:StringTableSize 的 2–3 倍(例如预估 8w,就设 262144)
  • 该参数必须在 JVM 启动时指定,运行中不可改
  • 增大后内存占用会上升(每个桶存一个指针,64 位下约 8 字节 × 桶数),但换来的是 O(1) 查找均摊成本
  • 可通过 jstat -gc 观察 CCSC(Compressed Class Space)或老年代增长趋势,判断是否真压到了元空间/堆

集合去重时,要不要先 intern() 再 add?

没必要,而且容易引入 bug。集合本身已靠 equals() 去重,再加一层 intern() 属于叠甲过度。

典型翻车点:某次上线后发现部分字符串去重失效,查下来是因为部分数据来自字面量(自动入池),部分来自 new String(buf) 后又 intern(),但另一批没 intern,导致同一内容在集合里存了两份。

  • 统一走 Set.add(str) 即可,语义明确,行为可预测
  • 如果真想复用字符串对象,应全链路控制构造方式(比如用 builder 模式封装字符串创建逻辑),而不是在集合入口打补丁
  • 极端内存敏感场景(如嵌入式 Java 或百万级短字符串缓存),才考虑用 ConcurrentHashMap.newKeySet() + 手动 intern(),但务必配套单元测试验证去重率和 GC 表现

真正难的不是选 intern() 还是 Set,而是搞清字符串来源、生命周期和复用边界——这些东西藏在业务代码深处,不会报错,但会让内存分析工具看起来像在解谜。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

436

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

543

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

317

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

81

2025.09.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

688

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1547

2023.10.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

488

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

68

2026.02.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号