通常我们需要把一些其它类型的值转换为String,这些类型可能就包括基本类型。如果你有2个甚至更多的基本类型变量位于字符串连接的开头处,那么你需要显示地把他们转换为String(否则 System.out.println(1+ ‘a’) 将打印98而不 是’la’).当然.你也可以使用String.valueOf方法(或者其他包装类的方法)


把一个字面量为空的字符串与一个基本类型的变量串连起来(在我们的示例中,”"+1)是最简单的方式,这个表达式的值就是一个字符串,你可以很安全地把任何基本类型值连接在后面—-编译器会很小心隐式地把他们转换成String。


不幸的是,这是能想象的最糟糕的方式,为了理解为什么是这样,我们需要查看下String连接操作在java中是被怎样运作的。 假如有一个String值(字面值、变量或方法的返回值) 后面跟随“+”这个操作符,再后面跟个其他任何表达式


String_exp + any_exp


java 编译器将会翻译成:


new StringBuilder().append(String_exp).append(any_exp).toString();


StringBuilder(String) 构造函数分配一个包含16个字符的缓冲,所以追加最多16个字符的StringBuilder不需要重新分配缓冲,但追加超过16个字符的将需要扩展缓冲。最后,StringBuilder.toString()方法中将会利用StringBuilder的缓冲拷贝一个新的String对象返回。


意味着一个单独的基本类型值转换为String的最坏一种情况是:你需要这样分配:一个StringBuilder,一个长度为16的char数组char[16],一个String和一个适合大小的char数组,用String.valueOf方法至少可以避免创建一个 StringBuilder。


有时你实际完全不需要把基本类型转换为String,例如:你解析一个被逗号符分割的String,最初的版本你可能会这样写


final int nextComma = str.indexOf("'");


甚至这样


final int nextComma = str.indexOf('\'');#注:反斜杠后面是两个单引号


之后程序可能需要扩展至支持任何分隔符,当然支持任何分隔符意味着你需要一个Stirng对象的分隔符并且使用String.indexof(String)方法.我们建议把一个默认的分隔符存储在m_separator 这变量中,代码看起来像这个:


private static List<String> split( final String str )

{

final List<String> res = new ArrayList<String>( 10 );

int pos, prev = 0;

while ( ( pos = str.indexOf( m_separator, prev ) ) != -1 )

{

res.add( str.substring( prev, pos ) );

prev = pos + m_separator.length(); // start from next char after separator

}

res.add( str.substring( prev ) );

return res;

}


但是后来你发现使用的分隔符从来就没有超过一个字符,在初始化时,你会定义一个char类型m_separtor来替换String类型的m_separtor并且适当的改变它的setter方法。但你又不想大量的改动解析方法(为什么我们如果改变这工作的代码呢?):


private static List<String> split2( final String str )

{

final List<String> res = new ArrayList<String>( 10 );

int pos, prev = 0;

while ( ( pos = str.indexOf("" + m_separatorChar, prev ) ) != -1 )

{

res.add( str.substring( prev, pos ) );

prev = pos + 1; // start from next char after separator

}

res.add( str.substring( prev ) );

return res;

}


如你所看到的,indexOf方法被更改了。但是它还是创建了一个字符串并且可用,当然这样并不对,因为String API中本来就有一个重载的indexOf方法,它可以接受char类型的参数,我们改动下:


private static List<String> split3( final String str )

{

final List<String> res = new ArrayList<String>( 10 );

int pos, prev = 0;

while ( ( pos = str.indexOf( m_separatorChar, prev ) ) != -1 )

{

res.add( str.substring( prev, pos ) );

prev = pos + 1; // start from next char after separator

}

res.add( str.substring( prev ) );

return res;

}


测试如下, “abc,def,ghi,jkl,mno,pqr,stu,vwx,yz” 这个字符串用这3种方法分别简析10次,下面是java 6_41 和 7_15的运行时间,java7的运行时间增加是因为String.subString方法变复杂 了,你可以阅读这里


http://java-performance.info/changes-to-string-java-1-7-0_06/


如你所看到的,这样简单的重构就使splitting这个方法执行的时间得到了一个客观的变化。



splitsplit2split3
Java 64.65 sec10.34 sec3.8 sec
Java 76.72 sec8.29 sec4.37 sec


更多相关文章

  1. Java 为什么需要保留基本数据类型
  2. 使用 ThreadLocal 变量的时机和方法
  3. Java 中关于 String 类型的 10 个问题
  4. clone 方法是如何工作的
  5. 不同类型业务系统技术架构的差异化
  6. VS中scanf等函数报错解决方法
  7. jQuery编程基础精华02(属性、表单过滤器,元素的each,表单选择器,子元
  8. jQuery的$.getJSON方法在IE浏览器下失效的解决方案
  9. JavaScript / jQuery:如何链接使用console.log()的方法

随机推荐

  1. Linux Mint 17下Sublime插件Emmet的安装
  2. Linux内核源代码情景分析读书笔记(5)-关于
  3. thinkphp连接mysql数据库查询数据显示
  4. Linux多线程实践(一)线程基本概念和理论
  5. 由看雪.Wifi万能钥匙 CTF 2017 第4题分析
  6. Linux操作系统三大应用领域
  7. Linux使用技巧11--Ubuntu离线安装openssh
  8. Linux下pwn从入门到放弃
  9. uclinux-2008R1.5-RC3(bf561)到VDSP5的移
  10. Linux 常用命令之文件和目录