本文部分内容来自于《突破程序员基本功的16课》,《Java程序性能优化》
1、拼接
1.1直接量拼接、变量拼接、fianl变量拼接
上干货,fuck goods
- public class StringTest {
- public static void main(String[] args) {
- test();
- test2();
- test3();
- }
- /**
- * 直接量拼接,对于编译期就能确定的值,编译器会将值合并
- * String hw = "hello" + "world";反编译class
- * 我们将看到
- * String hw = "helloworld";
- *
- * 所以hw == helloWorld 输出true
- */
- public static void test(){
- String hw = "hello" + "world";
- String helloWolrd = "helloworld";
- p(hw == helloWolrd);
- }
- /**
- * hw在编译期并不能确定值,因为h是变量,JVM在运行期才能确定其值
- * 会在运行期时,进行字串拼接生成新的字串对象,反编译class后
- * String hw = new StringBuilder(h).append("world");
- *
- * 输出false
- */
- public static void test2(){
- String h = "hello";
- String hw = h + "world";
- String helloWolrd = "helloworld";
- p(hw == helloWolrd);
- }
- /**
- * String hw = h + "world";虽然包含变量 h 的运算,但是编译器
- * 对fianl变量在编译期能确定其值,会发生宏替换,即:h变量替换成其值"hello",
- * 然后编译器会对直接量字串直接合并
- * String hw = h + "world";在编译完后就变成了 String hw = "helloworld";
- *
- * 输出 true
- *
- */
- public static void test3(){
- final String h = "hello";
- String hw = h + "world";
- String helloWolrd = "helloworld";
- p(hw == helloWolrd);
- }
- private static void p(boolean flag){
- System.out.println(flag);
- }
- }
1.2StringBuilder 和StirngBuffer
jdk5tiger以前,对于字符串拼接,例如:String hw = h + "wolrd",会产生临时变量,占用大量内存空间,需要程序员将 "+" 拼接改写成 StringBuffer.append();
java5提供了一个新的类用于字符串拼接StringBuilder,和StringBuffer略有区别,StringBuffer的方法是同步的,StringBuilder是非同步的。另外,java5的编译器会将 "+" 的字串,编译成StringBuilder.append(),也就是说,String str = a + b + c +d;这样的写法是不存在效率问题的,编译器帮你干了。
如无线程安全的要求,应该选择StringBuilder。
注意,编译器不是万能的
- //这样的写法在运行期,在循环内将会产生大量的 StringBuilder对象的实例,效率低下
- String str = "";
- for(int i = 0;i < 100000;i++){
- str += i;
- }
- //应该改成下面的写法
- StringBuilder sb = new StringBuilder();
- for(int i = 0;i < 100000;i++){
- sb.append(i);
- }
另外:StringBuilder有一个属性:容量,看下面构造函数
- /**
- * Constructs a string builder with no characters in it and an
- * initial capacity of 16 characters.
- */
- public StringBuilder() {
- super(16);
- }
- /**
- * Constructs a string builder with no characters in it and an
- * initial capacity specified by the <code>capacity</code> argument.
- *
- * @param capacity the initial capacity.
- * @throws NegativeArraySizeException if the <code>capacity</code>
- * argument is less than <code>0</code>.
- */
- public StringBuilder(int capacity) {
- super(capacity);
- }
StringBuilder的底层实现是char[]存储字串值,属性容量就是这个char[]数组的长度,默认是16,调用 append()方法时候,会先检查 (原字串长度+append新串长度) > 容量,如果超出,则是数组扩容为 (原字串长度+append新串长度 + 1) *2
结论:
(1)String str = "a" + "b" + "c";这样的直接量拼接,JVM将其视为String str = "abc";
(2)final变量的使用,同样也是有效率的。
(3)含有变量的拼接字串,String str = h + "world",在JDK5以上,大多数是不需要程序员改成StringBuilder或者StringBuffer的,但是在某些情况下是需要程序员写成StringBuilder/StringBuffer
(4)如果是大字串,需要多次调用 append,最好指定StringBuider 的容量,就像这样new StirngBuilder(1024),指定容量不要太大也不要太小,最好能预知构建完字串的长度,实在不知道也可以先预估一下
2、截取字符串
- public static void main(String[] args) {
- List<String> list = new ArrayList<String>();
- for(int i = 0;i < 100000;i++){
- String bigString = new String(new char[20*1024*1024]);
- String subStr = bigString.substring(1, 5);
- list.add(subStr);
- System.out.println("第几次" + i);
- }
- /*
- *第几次0
- 第几次1
- 第几次2
- 第几次3
- Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- at java.util.Arrays.copyOf(Arrays.java:2882)
- at java.lang.StringValue.from(StringValue.java:24)
- at java.lang.String.<init>(String.java:178)
- at StringTest.main(StringTest.java:9)
- */
- }
指定-Xmx10m时,JDK1.6 中,上面的代码就溢出了,因为substring(int,int)
看源码
- public String substring(int beginIndex, int endIndex) {
- if (beginIndex < 0) {
- throw new StringIndexOutOfBoundsException(beginIndex);
- }
- if (endIndex > count) {
- throw new StringIndexOutOfBoundsException(endIndex);
- }
- if (beginIndex > endIndex) {
- throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
- }
- return ((beginIndex == 0) && (endIndex == count)) ? this :
- new String(offset + beginIndex, endIndex - beginIndex, value);
- }
也就是说,String subStr = bigString.substring(1, 5);strStr的char[]属性值和bigString的char[]属性值是相同的,所以subStr所占的内存空间和bigString的内存空间也是相同的,虽然subString只能显示出几个字符 ,subStr这个实例的各属性值如下:
private final char value[] = bigString.value; private final int offset = 1; private final int count = 5; private int hash;
解决:
- String subStr = new String(bigString.substring(1, 5));
这样,就不会溢出了
还有一个解决办法,换成jdk7,则无此泄露点
结论:若是从大字串中截取出较小字串,应使用new String(bigString.substring(1, 5))构建新的字串
http://www.ibm.com/developerworks/cn/java/j-lo-optmizestring/#_ 表 _1._Java
相关推荐
php截断字符串优化函数 php截断字符串优化函数 php截断字符串优化函数
|PowerBuilder 数组字符串相互转化 天津 李华锋 * * | | * *PowerBuilder 数组字符串相互转化 完全免费 * ...|老数组转字符串212863 | |新数组转字符串187 * |以上是200000个数组测试结果 | |优化效率相当明显
SSO-23, 用于 C 的内存优化小字符串优化 SSO-23SSO-23是一个proof-of-concept字符串,它使用所有可用的SSO字节。 因此,当char类型是一个字节( 字符,有符号字符,无符号字符,等等 ) 和 64位 计算机上,这相当于一...
VB中对字符串的处理及其扩展VB技术很实用的源码本人看了很多网上有关的源码,基本上都是一样的,不过功能就不是很强大 有感与此,本人特写了一个功能强大点的欢迎大家使用
C strstr字符串查找函数优化,解决查找中文汉字匹配存在错误BUG问题。支持GBK、GB18030字符串。
功能是把定长字符串映射为整数,目的是找到比用C++标准库无序映射unordered_map更快的算法。所有字符串的长度都一样,且初始化之后只有查询,没有增删改。不同功能字符串长度也不同,但不超过16。本程序随机生成长度...
1.Convert.ToInt32与Int32.Parse的恩恩怨怨 2.Split的3种用法 3.@"abc"和"abc"区别在那里 4....交换两个指定位置字符的4种方法 8.“%10”的妙用 9.输出21个AAAAAAAAAAAAAAAAAAAAA的巧妙做法
在构建时将您的字符串集转换为优化的RegExps
VB 字符串高速链接例子
Java 实例 - 字符串优化源代码-详细教程.zip
一个java开发的小工具,一次性查找替换文本中多个字符串。 进行了优化: 1、不使用弹出式提示查找数据 2、添加替换还原功能
Delphi TMemo字符串的查找完全实现 已经完全的解决Delphi TMemo的查找对话框 和 替换对话框 功能 的所有功能 查看 GIF http://images.cnblogs.com/cnblogs_com/xe2011/524919/o_TFindDialog.gif
该资源是一个鲁棒性好,经过优化的C++字符串处理算法,包括分割字符串,自定义分隔符,字符串匹配,字符串搜索,不需要编译和安装。
Qstrings是一个字符串处理库,专门对速度进行了优化。包括字符串比较、字符大小写转换、OEM(Dos)和ANSI(Windows)互换、查找、替换、删除子串、删除字符、格式化、子串剪裁、字节字符串处理、整数和字符串互换等等...
这是我课余时间写的源码,暂时没有发现bug,如果您在使用过程中发现了bug,欢迎改正,同时欢迎您对此源码进行优化
将json、数组、数组json转换为字符串,基于jQuery,如果你觉得还有什么更优化的方法,请给我留言,大家可以一起探讨下
自己写了一个function 用于处理拆分时的逻辑运算,性能比网上找的快好几倍, 代码和说明:https://blog.csdn.net/jimyao37/article/details/123522885
实验设计优化字符串哈希函数 比较经典字符串哈希函数 采用斐波那契函数思想
该程序用C#编写,基于第三方类库实现TCP协议收发文本数据,比如Json,xml等字符串数据。SharpSocket底层采用Windows的IOCP模型,是最稳定和高效的Socket编程模型。SharpSocket代码经过精心优化, 有些直接在IL层编写,...
Wu/Manber是非常高效的字符串/文本搜索/查询/匹配算法