StringStringBuilderStringBuffer

Posted wcss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了StringStringBuilderStringBuffer相关的知识,希望对你有一定的参考价值。

一、String简单介绍

今天就简单的介绍一下String、StringBuilder、StringBuffer的区别,并没有深入的了解底层原理,不过用来面对面试还是可以的。

首先来看String的源码:技术图片

Java 提供了 String 类来创建和操作字符串。从源码可以看到String是被final修饰的所以String是不可被继承的,一经声明不得修改,所有的方法都是final方法。同时它还实现了Serializable、CharSequence、 Comparable接口。String是由字符数组组成的。所以一些常用的字符串基本操作不推荐使用String去完成。String并不是Java的8大基本类型之一,这一点很重要。

二、字符连接

“+”是java提供的双元运算符。可用来连接字符串。

public static void main(String[] args) {
String str = "iFillDream";
System.out.println(str + 2017);
}

如果项目需要频繁连接字符串时,这种方法就不太明智。接下来通过对比实验来测试以下String、StringBuilder、StringBuffer的速度;

public static void testStringAdd(){
long startTime = System.nanoTime();
String str = "";
for(int i=0;i<1000;i++){
str += "ifilldream" + "2017";
}
long endTime = System.nanoTime();
System.out.println("String+用时:" + (endTime - startTime) );
}

public static void testStringBuilderAdd(){
long startTime = System.nanoTime();
StringBuilder sb = new StringBuilder();
for(int i=0;i<1000;i++){
sb.append("ifilldream").append(2017);
}
long endTime = System.nanoTime();
System.out.println("StringBuilder用时:" + (endTime - startTime) );
}

public static void testStringBufferAdd(){
long startTime = System.nanoTime();
StringBuffer sb = new StringBuffer();
for(int i=0;i<1000;i++){
sb.append("ifilldream").append(2017);
}
long endTime = System.nanoTime();
System.out.println("StringBuffer用时:" + (endTime - startTime) );
}

通过实验测试得到以下结论:

技术图片

StringBuilder>StringBuffer>String

有人就要问了既然有了StringBuilder类为啥还需要一个StringBuffer类?通过源码可以得知StringBuilder和StringBuffer用法都是一样,几乎没啥区别。主要的区别在于StringBuffer很多成员方法加了synchronized关键字,使得StringBuffer是线程安全的,同时导致StringBuffer没有StringBuilder速度快。所以两者的区别在于线程安全性和效率上。此时对于采用StringBuffer和StringBuilder大家就有了答案了。

以下是 StringBuffer 类支持的主要方法:

序号方法描述
1 public StringBuffer append(String s)
将指定的字符串追加到此字符序列。
2 public StringBuffer reverse()
 将此字符序列用其反转形式取代。
3 public delete(int start, int end)
移除此序列的子字符串中的字符。
4 public insert(int offset, int i)
将 int 参数的字符串表示形式插入此序列中。
5 replace(int start, int end, String str)
使用给定 String 中的字符替换此序列的子字符串中的字符。

下面的列表里的方法和 String 类的方法类似:

序号方法描述
1 int capacity()
返回当前容量。
2 char charAt(int index)
返回此序列中指定索引处的 char 值。
3 void ensureCapacity(int minimumCapacity)
确保容量至少等于指定的最小值。
4 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将字符从此序列复制到目标字符数组 dst
5 int indexOf(String str)
返回第一次出现的指定子字符串在该字符串中的索引。
6 int indexOf(String str, int fromIndex)
从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。
7 int lastIndexOf(String str)
返回最右边出现的指定子字符串在此字符串中的索引。
8 int lastIndexOf(String str, int fromIndex)
返回 String 对象中子字符串最后出现的位置。
9 int length()
 返回长度(字符数)。
10 void setCharAt(int index, char ch)
将给定索引处的字符设置为 ch
11 void setLength(int newLength)
设置字符序列的长度。
12 CharSequence subSequence(int start, int end)
返回一个新的字符序列,该字符序列是此序列的子序列。
13 String substring(int start)
返回一个新的 String,它包含此字符序列当前所包含的字符子序列。
14 String substring(int start, int end)
返回一个新的 String,它包含此序列当前所包含的字符子序列。
15 String toString()
返回此序列中数据的字符串表示形式。

 

三、面试题

Q1:StringBuilder、StringBuffer、String的区别。

  1. String效率是最慢的,String拼接字符串时会new一个StringBuilder进行append操作,随后使用toString返回,易造成资源浪费,适用于少量的字符串操作的情况

  2. StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的

  3. StringBuilder和StringBuffer类的对象能够被多次的修改,且不产生新的未使用对象,而String则会生成新对象。

  4. StringBuilder适用于单线程下在字符缓冲区进行大量操作的情况

  5. StringBuffer适用多线程下在字符缓冲区进行大量操作的情况

Q2:以下代码输出结果是什么?

String a = "iFillDream2017";
String b = "iFillDream" + 2017;
System.out.println((a == b));

答:输出结果为true。"iFillDream"+2017在编译期间就已经被优化成"iFillDream2017",因此在运行期间,变量a和变量b指向的是同一个对象。

Q3:以下代码输出结果是什么?

String a = "iFillDream2017";
String b = "iFillDream";
String c = b + 2017;
System.out.println((a == c));

答:输出结果为false。由于有符号引用的存在,所以 String c = b + 2017;不会在编译期间被优化,不会把b+2017当做字面常量来处理的,因此这种方式生成的对象事实上是保存在堆上的。因此a和c指向的并不是同一个对象。

 

以上是关于StringStringBuilderStringBuffer的主要内容,如果未能解决你的问题,请参考以下文章