生活不仅眼前的苟且。还有读不懂的诗和到不了的远方。 --闫妮正则表达式
建议52:推荐使用String直接赋值算法
建议53:注意方法中传递的参数要求编程
建议54:正确使用String、StringBuffer、StringBuilder数组
建议55:注意字符串的位置安全
建议56:自由选择字符串的拼接方法app
建议57:推荐在复杂字符串操做中使用正则表达式性能
建议58:强烈建议使用UTF编码测试
建议59:对字符串持有一种宽容的心态ui
建议52:推荐使用String直接赋值this
建议53:注意方法中传递的参数要求
建议54:正确使用String、StringBuffer、StringBuilder
一、Java String类
字符串普遍应用在Java编程中,在Java中字符串属于对象,Java提供了String类来建立和操做字符串。
须要注意的是String的值是不可变的,这就致使每次对String的操做都会生成新的String对象,这样不只效率低下,并且浪费有限的内存空间。
咱们能够看到,初始String值为“hello”,而后在这个字符串后面加上新的字符串“world”,这个过程是须要从新在栈堆内存中开辟内存空间的,最终获得了“hello world”字符串也相应的须要开辟内存空间,这样短短的两个字符串,却须要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对常常性的字符串相关的操做,Java引入了两个新的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。
二、StringBuffer 和 StringBuilder 类
三者区别:
string:不可变字符序列
StringBuffer:可变字符序列、线程安全、效率低
StringBuilder:可变字符序列、线程不安全、效率高
注:
String的使用陷阱:
String ss = "a";
ss +="b";
若是屡次执行这些改变字符串内容的操做,会致使大量副本字符串对象存在内存中,下降效率。若是这样的操做放在循环中,会极大影响程序的性能。
三、性能测试
String的拼接与StringBuilder的使用对比,简单的12个字符串的循环解析拼接,相差了28毫秒,没有对比就没有伤害,之后用StringBuilder吧,暂时还不知道这个东西会有什么弊端,持续观察吧
建议55:注意字符串的位置
public class Client55 { public static void main(String[] args) { String str1 = 1 + 2 + "apples"; String str2 = "apples" + 1 + 2; System.out.println(str1); System.out.println(str2); } }
答案是不一致,str1的值是"3apples" ,str2的值是“apples12”。
建议56:自由选择字符串的拼接方法
package OSChina.Client; public class Client1 { public static void main(String[] args) { // 加号拼接 String str = ""; long start1 = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str += "江疏影"; } long end1 = System.currentTimeMillis(); System.out.println("加号拼接耗时:" + (end1 - start1) + "ms"); // concat拼接 str = ""; long start2 = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str = str.concat("江疏影"); } long end2 = System.currentTimeMillis(); System.out.println("concat拼接耗时:" + (end2 - start2) + "ms"); // StringBuilder拼接 str = ""; StringBuilder buffer = new StringBuilder(""); long start3 = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { buffer.append("江疏影"); } long end3 = System.currentTimeMillis(); System.out.println("StringBuilder拼接耗时:" + (end3 - start3) + "ms"); // StringBuffer拼接 str = ""; StringBuffer sb = new StringBuffer(""); long start4 = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { sb.append("江疏影"); } long end4 = System.currentTimeMillis(); System.out.println("StringBuffer拼接耗时:" + (end4 - start4) + "ms"); } }
从上面的执行结果来看,在字符串拼接方式中,StringBuilder的append方法最快,StringBuffer的append方法次之(由于StringBuffer的append方法是线程安全的,同步方法天然慢一点),其次是concat方法,加号最慢,这是为什么呢?
速度:StringBuilder>StringBuffer>concat>String+
原理:
一、“+”方法拼接字符串:
str= new StringBuilder(str).append("c").toString();
它与纯粹使用StringBuilder的append方法是不一样的:一是每次循环都会建立一个StringBuilder对象,二是每次执行完毕都要调用toString方法将其转换为字符串——它的执行时间就耗费在这里了!
二、concat方法拼接字符串:咱们从源码上看一下concat方法的实现,代码以下:
public String concat(String str) { int otherLen = str.length(); //若是追加字符长度为0,则返回字符串自己 if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); //产生一个新的字符串 return new String(buf, true); }
其总体看上去就是一个数组拷贝,虽然在内存中处理都是原子性操做,速度很是快,不过,注意看最后的return语句,每次concat操做都会建立一个String对象,这就是concat速度慢下来的真正缘由,它建立了10万个String对象呀。
三、append方法拼接字符串:StringBuilder的append方法直接由父类AbstractStringBuilder实现,其代码以下:
public AbstractStringBuilder append(String str) { //若是是null值,则把null做为字符串处理 if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); //字符串复制到目标数组 str.getChars(0, len, value, count); count += len; return this; }
整个append方法都在作字符数组处理,加长,而后拷贝数组,这些都是基本的数据处理,没有建立任何对象,因此速度也就最快。
四、StringBuffer的处理和此相似,只是方法是同步的而已。
建议57:推荐在复杂字符串操做中使用正则表达式
建议58:强烈建议使用UTF编码
注:一个系统使用统一的编码。
建议59:对字符串持有一种宽容的心态
中文的排序问题很混乱,Java使用UNICODE编码,而中文UNICODE字符集来源于GB2312,GB2312是一个包含了7000多个字符的字符集,它是按照拼音排序,而且是连续的,以后的GBK、GB18030都是在其基础上扩充而来的,因此要让它们完整的排序也就难上加难了。
若是排序对象是常用的汉字,使用Collator类排序彻底能够知足咱们的要求,毕竟GB2312已经包含了大部分的汉字,若是须要严格排序,则要使用一些开源项目来本身实现了。
注意:若是排序不是一个关键算法,使用Collator类便可。