1、String、StringBuilder、StringBuffer
这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面。
首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。以下面一段代码为例:
String str=”abc”;
System.out.println(str);
str=str+”de”;
System.out.println(str);
如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。
而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
另外,有时候我们会这样对字符串进行赋值
String str=”abc”+”de”;
StringBuilder stringBuilder=new StringBuilder().append(“abc”).append(“de”);
System.out.println(str);
System.out.println(stringBuilder.toString());
这样输出结果也是“abcde”和“abcde”,但是String的速度却比StringBuilder的反应速度要快很多,这是因为第1行中的操作和
String str=”abcde”;
是完全一样的,所以会很快,而如果写成下面这种形式
String str1=”abc”;
String str2=”de”;
String str=str1+str2;
那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。
2. 再来说线程安全
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
3. 总结一下
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
2、Java中String,StringBuffer,StringBuilder常用方法及使用实例
1 . String类中常用方法
- char charAt(int index)
返回指定索引处的 char 值。 - int compareTo(String anotherString)
按字典顺序比较两个字符串。实际上返回的是字符ASCII码的差值,但通常只关心正负还是0 - boolean contains(CharSequence s)
当且仅当此字符串包含指定的 char 值序列时,返回 true。 - boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。还可以指定开始检测位置下标
boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。 - boolean equals(Object anObject)
将此字符串与指定的对象比较。已覆写,比较内容是否相等 - void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将字符从此字符串复制到目标字符数组。 - int hashCode()
返回此字符串的哈希码。 - int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。 没有则返回-1
int indexOf(int ch, int fromIndex)
返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。
int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
int lastIndexOf(int ch)
返回指定字符在此字符串中最后一次出现处的索引。
int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
int lastIndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引。
int lastIndexOf(String str, int fromIndex)
返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 - int length()
返回此字符串的长度。 - boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。 - String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement)
使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 - String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。 - String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。
String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。 - char[] toCharArray()
将此字符串转换为一个新的字符数组。 - String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
String toLowerCase(Locale locale)
使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。
String toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
String toUpperCase(Locale locale)
使用给定 Locale 的规则将此 String 中的所有字符都转换为大写 - String toString()
返回此对象本身。
public class StringOpera
{
public static void main(String[] args)
{
String[] str1 = { "NBA", "ABC", "Mike", "NBA", "NG", "OK", "NBA" };
stringSort(str1);
stringPrint(str1);
String str2 = "jhabchjabckokabc";
System.out.println(substringCount(str2, "abc"));
String strA = "tryyufgasdkjkabcdeijr";
String strB = "asdabcde";
String com = maxCommon(strA, strB);
System.out.println(com);
}
// 获取两个字符串中最大公共子串
public static String maxCommon(String stringA, String stringB)
{
String strMax = null, strMin = null;
// 找到長度大的
if (stringA.length() >= stringB.length())
{
strMax = stringA;
strMin = stringB;
} else
{
strMax = stringB;
strMin = stringA;
}
// 双层循环
for (int i = 0; i < strMin.length(); i++)
for (int j = 0, l = strMin.length() - i; l != strMin.length() + 1; j++, l++)
{
String com = strMin.substring(j, l);
if (strMax.contains(com))
return com;
}
return null;
}
// 打印
public static void stringPrint(String[] str1)
{
for (int i = 0; i < str1.length; i++)
System.out.print(str1[i] + " ");
}
// 字符串数组排序
public static void stringSort(String[] string)
{
for (int i = 0; i < string.length - 1; i++)
for (int j = i + 1; j < string.length; j++)
if (string[i].compareTo(string[j]) > 0)
StringOpera.swap(string, i, j);
}
// 子串出现次数
public static int substringCount(String str2, String substring)
{
int count = 0;
for (int index = 0; index < str2.length(); index++)
if ((index = str2.indexOf(substring, index)) != -1)
{
index = index + substring.length();
count = count + 1;
}
return count;
}
// 交换
public static void swap(String[] strArry, int i, int j)
{
String temp = strArry[i];
strArry[i] = strArry[j];
strArry[j] = temp;
}
}
- StringBuffer
用于存储数据的容器。类似于字符串缓冲区,池子不能修改,但是“内容”可以通过方法修改,最主要的两个方法就是 append 和 insert 方法
特点:
长度的可变的。
可以存储不同类型数据。
最终要转成字符串进行使用。
可以对字符串进行修改。
线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
- 增
StringBuffer append(data);尾部添加
StringBuffer insert(index,data);指定未知插入
eg:
StringBuffer sb=new StringBuffer(“abc”);
sb.append(“de”);
//打印sb 为abcde - 删
StringBuffer delete(int start, int end)
StringBuffer deleteCharAt(int index):删除指定位置的元素
eg:
sb.delete(0,sb.length()); - 改
StringBuffer replace(start,end,string);
void setCharAt(index,char); 查
char charAt(index);
int indexOf(string);StringBuilder
功能和StringBuilder几乎一模一样,但是无线程安全,从1.5版本开始
为了提高效率,在单线程中尽量使用StringBuilder。