String、StringBuffer、StringBuilder的区别和转换
- String:不可变字符序列;底层使用char[]存储
- StringBuffer:可变字符序列;线程安全,效率低;底层使用char[]存储
- StringBuilder:可变字符序列;jdk5.0新增,线程不安全,效率高;底层使用char[]存储
- 执行效率:StringBuilder>StringBuffer>String
StringBuffer和StringBuilder的内存解析
/*先看String不可变的原因
创建一个char型数组来存放'a'、'b'、'c',char[] value = new char[]{'a','b','c'}
数组创建后长度不可变,故导致String不可变
*/
String s1 = new String("abc");
/*再看StringBuffer可变的原理
实际上是直接创建一个大的数组来存放字符串的字符序列,
使得表面看起来可以改变字符串,一旦超出该容器数组的长度
需要进行扩容
*/
StringBuffer s2 = new StringBuffer["abc"];//char[] value = new char["abc".length+16]
注意:
1.s2.length()得到的长度是3而不是19
2.扩容底层数组,默认是原来容量2倍+2,同时将原数组的元素复制到新数组
StringBuilder和StringBuffer常用方法
StringBuilder s1 = new StringBuilder("abc");
StringBuffer s2 = new StringBuffer("xyz");
//增
s1.append("d");//s1-->abcd
s2.append("o");//s2-->xyzo
//删
s1.delete(0,1);//s1-->bc,左闭右开
//改
s1.setCharAt(0,'x');//s1-->xbc
或
s1.replace(0,2,"xy");//s1-->xyc,左闭右开
//查
s1.charAt(2);//c
s1.indexOf("b");//1
//插
s1.insert(0,"x");//s1-->xabc
//长度
s1.length();//3
//遍历
for+charAt()
或
for+toString()
String编码和解码
判断字符串是否为空(null、""、" ")
import org.apache.commons.lang3.StringUtils;//需要导入第三方工具类
public class Application {
public static void main(String[] args) {
String s1 = null;
String s2 = "";
String s3 = " ";
System.out.println(StringUtils.isBlank(s1));//true
System.out.println(StringUtils.isBlank(s2));//true
System.out.println(StringUtils.isBlank(s3));//true
System.out.println(StringUtils.isEmpty(s1));//true
System.out.println(StringUtils.isEmpty(s2));//true
System.out.println(StringUtils.isEmpty(s3));//false
}
}
String常用方法
@Test
public void test() {
//创建字符串对象
String str1 = "abc";
String str2 = new String("abc");
//字符串长度
System.out.println(str1.length());//字符长度,不是字节长度
//大小写转换
System.out.println(str1.toUpperCase());//"ABC",不改变原字符串,String不可变
System.out.println("ABC".toLowerCase());//"abc"
//判断起止字符
System.out.println("abc".startsWith("a"));//true
System.out.println(str1.endsWith("bc"));//true
//判断包含字符子串
System.out.println(str1.contains("a"));//true
//根据索引寻找字符
System.out.println(str1.charAt(1));//'b'
//根据字符获取索引
System.out.println(str1.indexOf("b"));//1
//指定起始位置,返回字符的索引
System.out.println("abcabc".indexOf("a", 2));
//根据缩影找子串
System.out.println("abcd".substring(1,3));//"bc"
//根据子串找索引
System.out.println("abcd".indexOf("bc"));//1,返回第一个符合条件的起始index
System.out.println("abcde".lastIndexOf("bc"));//1
//字符串拼接
System.out.println("abc".concat("123"));//"abc123",拼接并创建新字符串
//判空
System.out.println(str1.isEmpty());//false
System.out.println(str1.length()==0);//false
//System.out.println(null.isEmpty());//空指针异常
//字符串替换
System.out.println(str1.replace("abc", "AB"));//"AB"
//去除前后空格
System.out.println(" a c ".trim());//"a c"
//equals()继承Object类,判断两个对象value值是否相等,返回boolean
String str1 = "abc";
String str2 = "abc";
System.out.println(str1.equals(str2));//true
System.out.println(str1==str2);//true,str1和str2都指向字符串常量池中的同一个地址
//使用new关键赋值
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3.equals(str4));//true
System.out.println(str3==str4);//false
//compareTo(),必须实现Comparable接口,重写方法。比较两个对象的大小,返回int
String str5 = "zuozs";
String str6 = "zuozs";
System.out.println(str5.compareTo(str6));//0
//字符串和数组的转换
String str7 = "abcde";
char[] charr1 = str7.toCharArray();
char[] charr2 = {'a','b','c','d','e'};
String str8 = new String(charr1);
String str9 = new String(charr2,1,3);//bcd
}
“+”运算符拼接字符串的优化
@Test
public void test() {
//字面常量拼接,底层自动优化成一个字符串str = "abc"
String str = "a"+"b"+"c";
String str1 = "a";
String str2 = "b";
String str3 = "c";
//变量使用"+"拼接,虚拟机会自动转变成StringBuilder进行append计算
String str4 = str1+str2+str3;
String str5 = "";
//虽然底层会转变成StringBuilder来计算,但在循环中依然效率低下
for (int i = 0; i < 100; i++) {
str5 = str5 + i;
//每次循环都会创建一个builder对象
//StringBuilder builder = new StringBuilder(str5);
//builder.append(i);
//str5 = builder.toString();
}
StringBuilder builder = new StringBuilder();
//整个循环期间都只创建了一个builder对象
for (int i = 0; i < 100; i++) {
builder.append(i);
}
}