基本类型转String

ImportNew  •  扫码分享
我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。  
分享到:


本文由 ImportNew - ImportNew读者 翻译自 java-performance。如需转载本文,请先参见文章末尾处的转载要求。

文章由 @邋遢爱好者 翻译, 并由ImportNew团队成员整理了全文。如果你也希望参与类似的系列文章翻译,可以加入我们的Java开发 和 技术翻译 小组。

通常我们需要把一些其它类型的值转换为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方法变复杂 了,你可以阅读这里

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

split split2 split3
Java 6 4.65 sec 10.34 sec 3.8 sec
Java 7 6.72 sec 8.29 sec 4.37 sec

原文链接: java-performance 翻译: ImportNew.com - ImportNew读者
译文链接: http://www.importnew.com/7550.html
[ 转载请保留原文出处、译者和译文链接。]



相关文章

随意打赏

提交建议
微信扫一扫,分享给好友吧。