下文以StringBuffer为例
前面我们用字符串做拼接,比较耗时并且也耗内存(每次都会构造一个新的string对象),而这种拼接操作又是比较常见的,为了解决这个问题,Java就提供了两个字符串缓冲区类。StringBuffer和StringBuilder供我们使用。
String 长度大小不可变
StringBuffer 长度可变、线程安全、速度较慢
StringBuilder 长度可变、线程不安全、速度最快
-----------------------------------------------------------------------------------------------------------------
StringBuilder:线程非安全的
StringBuffer:线程是安全的(synchronized关键字进行修饰)
当我们在字符串缓冲区被多个线程使用时,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
1.如果要操作少量的数据用 = String
2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
//无参构造方法 StringBuffer() //指定容量的字符串缓冲区对象 StringBuffer(int size) //指定字符串内容的字符串缓冲区对象 StringBuffer(String str)
//可以把任意类型添加到字符串缓冲区里,并且返回字符串缓冲区本身(this) public StringBuffer append (String str) //在offset位置把任意类型的数据插入到字符串缓冲区中,并且返回字符串缓冲区本身(this) public StringBuffer insert(int offset,String str)
//删除指定位置的字符,并且返回本身 public StringBuffer deleteCharAt(int index) //删除从指定位置开始指定位置结束的内容,并且返回本身 public StringBuffer delete(int start, int end)
//从start到end用str代替 public StringBuffer replace(int start,int end,String str)
//Eg: 好你界世 → 世界你好 public StringBuffer reverse()
//从start位置开始截取,取以后字符串,但不返回本身,原数据不影响 public String substring(int start) //截取start到end之间的字符串 Publci Stirng substring(int start, int end)
String → StringBuffer 是为了使用后者的功能
StringBuffer → String 可能需要后者的类型
String s = “Hello” //通过构造方法 StringBuffer a = new StringBuffer(s); //通过append()方法 StringBuffer a = new StringBuffer(); a.append(s);
StringBuffer buffer = new StringBuffer(“java”) //通过构造方法 String str = new String (buffer); //通过toString()方法 String str = buffer.toString();
(String类中的 “+”“+=”是java中仅有的两个重载过的运算符)
所以我们可以通过“+”符号 将多个字符串进行拼接
将这段代码利用 javap -c filename 反编译
我们可以看到代码被编译器自动优化成使用StringBuilder方式拼接
运行效率得到了保证
下面一个案例 数组拼接成指定格式的字符串 代码中使用了循环语句
//在循环中通过String拼接字符串 public class StringBuilderDemo { public static void main(String[] args) { String[] arr = {"Hello", "World", "!!!"}; String s1 = arrayToString(arr); System.out.println(s1); } public static String arrayToString(String[] arr) { String s = ""; s += "["; for (int x = 0; x < arr.length; x++) { if (x == arr.length - 1) { s += arr[x]; } else { s += arr[x]; s += ", "; } } s += "]"; return s; } } //运行结果 [Hello, World, !!!]
使用String方式进行拼接,我们反编译可以看到,StringBuilder被创建在循环的内部,这意味着每循环一次就会创建一次StringBuilder对象,这可是一个糟糕的事情。
//在循环中使用StringBuilder拼接字符串 public class StringBuilderDemo2 { public static void main(String[] args) { String[] arr = {"Hello", "World", "!!!"}; String s1 = arrayToString(arr); System.out.println(s1); } public static String arrayToString(String[] arr) { StringBuilder s = new StringBuilder(); s.append("["); for (int x = 0; x < arr.length; x++) { if (x == arr.length - 1) { s.append(arr[x]); } else { s.append(arr[x]); s.append(", "); } } s.append("]"); return s.toString(); } } //运行结果 [Hello, World, !!!]
使用StringBuilder方式进行拼接,反汇编代码,可以看到,不仅循环部分的代码更为简洁,而且它只生成了一个StringBuilder对象。显式的创建StringBuilder对象还允许你预先为其指定大小。可以避免多次重新分配缓冲。
如果字符串操作比较简单,就可以使用“+”运算符操作,编译器会为你合理的构造出最终的字符串结果
如果使用循环语句 最好自己手动创建一个StringBuilder对象,用它来构最终结果
如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !^_^
如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)
一个坚持推送原创Java技术的公众号:理想二旬不止