字符串
字符串相关API
String
、StringBuilder
、StringJoiner
、StringBuffer
、Pattern
、Matcher
String
java.lang.String
类,Java中的所有字符串文字都是该类的对象。使用的时候不需要导包
注意点:
字符串的内容是不会发生改变的,它的对象在创建后不能被更改,字符串拼接之后是创建了一个新的字符串
创建String对象的两种方式
- 直接赋值:
String name = "lucy";
- new:
// 空参构造
String name = new String(); // name-""
// 带参构造,根据传递的字符串内容再创建一个新的字符串对象
String name = new String("abc");
// 传递字符数组,根据字符数组的内容创建一个新的字符串对象
// 应用场景:修改字符串的内容。abc-> qbc
// abc -> {'a', 'b', 'c'} -> {'q', 'b', 'c'} -> qbc
char[] chs = {'a', 'b', 'c', 'd'};
String str = new String(chs); // "abcd"
// 传递字节数组,根据字节数组内容创建一个新的字符对象
// 应用场景:网络中传输的数据都是字节信息
// 把字节信息转换为字符串,此时就用到了这种方式
byte[] bytes = {97, 98, 99, 100};
String sbt = new String(bytes); // "abcd"
字符串在内存中的运行方式
Java的内存模型中有一个StringTable(串池)
,在JDK7以前,是在方法区的;从JDK7开始,欧诺个方法区中挪到了堆内存。
- 当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在。如果不存在,创建新的;如果存在,就复用
- new出来的字符串,不会复用
字符串的比较
比较以下两个字符串
String s1 = new String("abc"); // 记录的是堆里面的地址
String s2 = "abc"; // 记录的是串池里的地址
sout(s1 == s2); // false
==比较比的是什么?
对于基本数据类型来说,比的是实际的数据值
对于引用数据类型来说,比的是地址值
那么如何比较两个字符串呢?
str1.equals(str2)
:完全一样才是true,否则是falsestr1.equalsIgnoreCase(str2)
:忽略大小写的比较
键盘录入的字符串和自定义的字符串比较: 也是返回false
结论: 以后只要想比较字符串,就用String类的比较方法
StringBuilder
是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
StringBuilder构造方法
- 空参构造:
StringBuilder()
创建一个空白可变字符串对象,不含有任何内容 - 带参构造:
StringBuilder(str)
根据字符串内容,创建可变字符串对象
StringBuilder常用方法
append(任意类型)
:添加数据,并返回对象本身reverse()
:反转容器中的内容length()
:返回长度toString()
:把StringBuilder转换为String
StringBuilder是java已经写好的类,在底层对他做了一些特殊处理,打印对象不是地址值而是属性值
StringBuilder使用场景
- 字符串的拼接
- 字符串的反转
StringJoiner
与StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
JDK8之后出现的
StringJoiner的构造方法
StringJoiner(间隔符号)
:创建一个StringJoiner对象,指定拼接时的间隔符号StringJoiner(间隔符号,开始符号,结束符号)
:创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号- 例:
StringJoiner sj = new StringJoiner("---")
StringJoiner的成员方法
add(添加的内容)
:添加数据,并返回对象本身length()
:返回长度toString
:返回一个字符串
字符串开发常见案例
字符串相关底层原理
字符串拼接的底层原理
第一种情况:等号右边没有变量,全是字符串
String s = "a" + "b" + "c"
会触发字符串的优化机制,在编译的时候已经是最终结果了
第二种情况,在拼接的时候有变量参与
在内存中创建了很多对象,浪费空间,时间也很慢
String s1 = "a";
String s2 = s1+"b";
String s3 = s2 + "c";
在JDK8以前,会使用StringBuilder,一个加号,堆内存中至少会有两个对象
JDK8以后,会先预估最终字符串的长度并创建一个数组,这里的预估长度也是极其耗时的
结论
如果很多字符串变量拼接,不要直接+。在底层会创建多个对象,浪费时间,浪费性能
StringBuilder提高效率的原理图
StringBuilder是一个内容可变的容器,所有拼接的都会StringBuilder中放,不会创建无用空间,节约内存
StringBuilder源码分析
- 默认创建一个默认为16的字节数组
- 如果添加的内容长度小于16,直接存;如果大于16会扩容,原来的容量*2+2
- 如果扩容之后还不够,以实际长度为准
sb.capacity()
获得容量;sb.length();
获得长度