`
chenshuyi
  • 浏览: 26041 次
文章分类
社区版块
存档分类
最新评论

字符串缓冲池

 
阅读更多
看到一个关于字符串缓冲池的讨论

(转)
大家先来看看一段奇怪的程序:
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = "Monday";
}
}
这个程序真是简单啊!可是有什么问题呢?

1. 来自 String 的忧虑
上面这段程序中,到底有几个对象呢?
可能很多人脱口而出:两个,s1 和 s2
为什么?
String 是 final 类,它的值不可变。
看起来似乎很有道理,那么来检测一下吧,稍微改动一下程序
就可以看到结果了:

public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = "Monday";
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
}
}
呵呵,很多人都会说已经不止两个对象了
编译并运行程序,输出:s1 == s2
啊!
为什么 s1 == s2 ?
== 分明是在说:s1 与 s2 引用同一个 String 对象 -- "Monday"!

2. 千变万化的 String
再稍微改动一下程序,会有更奇怪的发现:
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else
System.out.println("s1 not equals s2");
}
}
我们将 s2 用 new 操作符创建
程序输出:
s1 != s2
s1 equals s2
嗯,很明显嘛
s1 s2分别引用了两个"Monday"String对象
可是为什么两段程序不一样呢?

3. 在 String 的游泳池中游泳
哈哈,翻了翻书终于找到了答案:
原来,程序在运行的时候会创建一个字符串缓冲池
当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会
在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被
放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1
将 s2 引用 s1 所引用的对象"Monday"

第二段程序中,使用了 new 操作符,他明白的告诉程序:
“我要一个新的!不要旧的!”与是一个新的"Monday"Sting对象被创
建在内存中。他们的值相同,但是位置不同,一个在池中游泳
一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?

4. 继续潜水
再次更改程序:
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern();
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else
System.out.println("s1 not equals s2");
}
}

这次加入:s2 = s2.intern();

补充:

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。 用intern可以提高堆内存的利用率。

哇!程序输出:
s1 == s2
s1 equals s2
原来,程序新建了 s2 之后,又用intern()把他打翻在了池里
哈哈,这次 s2 和 s1 有引用了同样的对象了
我们成功的减少了内存的占用

5. == 与 equals() 的争斗
String 是个对象,要对比两个不同的String对象的值是否相同
明显的要用到 equals() 这个方法
可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,
哦,天哪,真慢啊
更好的办法:
把所有的String都intern()到缓冲池去吧
最好在用到new的时候就进行这个操作
String s2 = new String("Monday").intern();
这样大家都在水池里泡着了 。
分享到:
评论

相关推荐

    Python小整数对象池和字符串intern实例解析

    python为了提高效率,节省内存,在实现上大量使用了缓冲池技术和字符串intern技术。 整数和字符串是不可变对象,也就意味着可以用来共享,如100个“python”字串变量可以共享一个“python”字符串对象,而不是创建...

    高性能静态缓冲字符串

    自动的字符串类。 托管内存池和性能调整+支持模块

    libngx:关于nginx核心数据结构的静态库包括数组、缓冲区、哈希、列表、队列、树、字符串和内存池

    库 关于nginx核心数据结构的静态库包括数组、缓冲区、哈希、列表、队列、树、字符串和内存池

    Java String类的使用详解

    Java String类一、String类概述及特点1.概述2.特点二、字符串的创建及常量池的概念1....字符串缓冲区支持可变的字符串。因为String 对象是不可变的,所以可以共享。 字符串效果上相当于char[]数组,

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    varchar2 1~4000字节 可变长度字符串,与CHAR类型相比,使用VARCHAR2可以节省磁盘空间,但查询效率没有char类型高 数值类型 Number(m,n) m(1~38) n(-84~127) 可以存储正数、负数、零、定点数和精度为38位的浮点数...

    C语言实现生产者消费者问题

    C语言实现生产者消费者问题,分配具有n个缓冲区的缓冲池,作为共享资源。 定义两个资源型信号量empty 和full,empty信号量表示当前空的缓冲区数量,full表示当前满的缓冲区数量。 定义互斥信号量mutex,当某个进程...

    fmt:格式化库作为 C stdio 和 C++ iostreams 的替代方案-开源

    该库是完全类型安全的,自动内存管理可防止缓冲区溢出,使用异常或在编译时报告格式字符串中的错误。 该库生成紧凑的每次调用编译代码。 该库是高度可移植的,仅依赖于一小组 C++11 特性,如可变参数模板、类型特征...

    Java设计模式之享元模式.docx

    享元即为分享元素,字符串常量池、数据库连接池、缓冲池都是是这个道理。该模式的意图为:运用共享技术有效地支持大量细粒度的对象。 就像上边的例子中,Integer类会把较小的数字保存起来,再次新建比较小的Integer...

    C程序范例宝典(基础代码详解)

    实例038 不用strcat连接两个字符串 46 实例039 删除字符串中连续字符 47 实例040 字符升序排列 49 实例041 在指定的位置后插入字符串 50 1.7 函数 51 实例042 求字符串中字符的个数 51 实例043 递归...

    Golang2-new.docx

    3.3.5. 字符串的 for range 循环 40 3.3.6. 用字节切片构造字符串 41 3.3.7. 用rune切片构造字符串 42 3.3.8. 字符串的长度 42 3.3.9. 字符串是不可变的 42 3.3.10. UTF8(go圣经) 43 3.4. 常量 45 3.4.1. ...

    c语言经典案例

    实例097 计算字符串中有多少个单词 126 实例098 不使用strcpy()函数实现 字符串复制功能 127 实例099 逆序存放数据 129 实例100 相邻元素之和 130 实例101 选票统计 131 实例102 使用数组统计学生成绩 132 实例103 ...

    Nginx 0.8.33最新版源码

    nginx的源码质量也相当高,作者“家酿”了许多代码,自造了不少轮子,诸如内存池、缓冲区、字符串、链表、红黑树等经典数据结构,事件驱动模型,http解析,各种子处理模块,甚至是自动编译脚本都是作者根据自己的...

    ConcurrentApplication

    构建并发应用程序客观的该... 该字符串随后被写入输出缓冲区流并等待来自服务器的响应。 如果服务器池已满,客户端将通知用户未收到响应。 客户端将继续运行,直到用户在提示中键入“停止”。 这将触发返回,并且客户

    golandia:使用代码示例动手介绍Go

    字符串函数 字符串格式 常用表达 JSON格式 XML格式 时间 时代 时间格式/解析 随机数 号码解析 URL解析 SHA1哈希 Base64编码 读取文件 写文件 线路滤波器 文件路径 目录 临时文件和目录 测验 ...

    MAT 文件库:从 Java 读取和写入 MAT 文件-matlab开发

    附加功能包括: * 流畅的API *高级过滤* 并发压缩* 自定义压缩级别*增量写入和附加到现有文件* 自定义类的序列化* 大矩阵的内存映射存储*自定义缓冲池* EJML 矩阵类型的直接序列化 有关更多信息,请查看 Github 上...

    全球采矿区域边界数据集(1km)-v2-30arcsecond.tif

    它包含 44,929 个面要素,覆盖全球采矿业使用的 101,583 平方公里土地,包括大规模、手工和小规模采矿。...主要数据集由一个地理包 (GPKG) 文件组成,其中包括以下变量:ISO3_CODE<字符串>、COUNTRY

    c#学习方法

    课程内容:讲解粒子系统、Mecanim、导航寻路、Unity游戏移植技术、Mecanim 动画系统、导航寻路、项目研发常用优化策略、Unity游戏移植与手指触控识别、射线、数据持久化、对象缓冲池技术、物理学模拟(铰链关节...

    提高程序性能Microsoft.IO.RecyclableMemoryStream.zip

    每个流可以有一个标识字符串标签,用在日志中——帮助当发现错误和内存泄漏 可灵活的调节池算法极限 标签:Microsoft 分享 ...

    db2-技术经验总结

    1.11. 格式化字符串(原) 33 1.12. 10大DB2优化技巧 33 1.13. 使用DB2的整数转换浮点小数时注意(原) 41 1.14. 使用递归制造测试数据(原) 42 1.15. 尽量使用自定义函数来代替存储过程 42 1.16. VALUES(…) 与 VALUES ...

    Windows内核安全与驱动开发光盘源码

    2.2.3 字符串 20 2.3 重要的数据结构 21 2.3.1 驱动对象 21 2.3.2 设备对象 22 2.3.3 请求 24 2.4 函数调用 25 2.4.1 查阅帮助 25 2.4.2 帮助中有的几类函数 26 2.4.3 帮助中没有的函数 28 2.5 Windows的...

Global site tag (gtag.js) - Google Analytics