一、认识String类
1.认识
String在Java中是字符串类型,但与其他类型不同。它是一个类,可以创建对象的类。与int、char等自待类型有些许不同。但它仍然是java提供的一种类型。
类中有4个属性,这里主要认识一下value属性。它是实际存放字符串的引用。那么我们来看一下源码:
2.String的不可变性
可以看到value数组被final修饰,那么他里面的值是不可以变的。但是java又提供了非常多对String类操作的方法,对里面的value数组进行更改。但是实际上,他都是创建一个新的String类对其进行操作,并返回新的String类。
这样会有一个非常大的问题,有这样一个代码:
public static void main(String[] args) {
String array = "a";
for (int i = 0; i < 1000; i++) {
//他在这里会不停的发生创建新的对象
//并进行拼接
//然后再返回新的对象
array += i;
}
System.out.println(array);
}
这会大大提升时间空间复杂度
那么以后在使用字符串并且,对字符串进行大量操作,或者不想创建新的String类的时候可以使用StringBuilder和StringBuffer
二、StringBuilder和StringBuffer
1.StringBuilder和Strinig的区别
这里使用StringBuilder进行对比
正常使用StirngBuilder进行拼接:
public static void main(String[] args) {
StringBuilder s = new StringBuilder("a");
for (int i = 0; i < 1000; i++) {
s.append(i);//想当与String的+=
}
System.out.println(s.toString());
}
用StringBuilder模拟Stirng进行拼接:
public static void main(String[] args) {
StringBuilder s1 = new StringBuilder("a");
for (int i = 0; i < 1000; i++) {
StringBuilder tmp = new StringBuilder("");
tmp = s1.append(i);
}
System.out.println(s1.toString());
}
创建类本来就是一个复杂的过程,如果使用String他会创建1000次,那速度肯定是大大降低。
StringBuffer也是跟StringBuilder相同的操作,那StringBuilder和StringBuffer有哪些区别呢?这也是面试常考题
2.String、StringBuffer、StringBuilder的区别
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
- StringBuffer与StringBuilder大部分功能是相似的
- StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
这个第3项给大家解释一下:想要真正了解这个东西需要多线程的理解,这里给大家简单解释一下。
一边看图一边看我解释:
厕所可以看作是一种资源吧
StringBuffer更像家里的厕所,是有锁的。你在上厕所(你在使用资源)别人是进不来的。
StirngBuilder更像是公共场所,没有锁想进来就进来,那肯定没有家里的厕所有安全感。
所以:StringBuffer是安全的,StringBuilder是不安全的。但目前我们写的程序都是单线程的
3.String、StringBuffer、StringBuilder的运行时间区别
使用System.currentTimeMillis()方法可以获取当前时间的一个毫秒数。
用 当前时间-指向前时间 = 时间差
public static void main(String[] args) {
long start = System.currentTimeMillis();//获得当前时间毫秒数
String s = "";
for(int i = 0; i < 100000; ++i){
s += i;
}
long end = System.currentTimeMillis();
System.out.println("String" + (end - start));
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for(int i = 0; i < 100000; ++i){
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuffer" + (end - start));
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for(int i = 0; i < 100000; ++i){
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuilder" + (end - start));
}
结果:
可以看到String与StirngBuilder和StringBuffer的区别是巨大的。但这里并没有体现出StirngBuilder和StringBuffer之间的差距,可能是现在做了优化。不过在不涉及多线程的时候推荐使用StirngBuilder要更快一点。
三、StringBuilder和StringBuffer的常用方法
想要了解String常用方法的可以看我这篇博客:String类和String类常用方法-CSDN博客
1. StringBuff append(String str) 拼接字符串
StringBuff append(String str) | 在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量 |
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("");
int[] arr = new int[]{1,2,3,4,5};
stringBuilder.append("a");
stringBuilder.append(1);
stringBuilder.append(1.5);
stringBuilder.append('c');
for (int a: arr) {
stringBuilder.append(a);
}
System.out.println(stringBuilder.toString());//a11.5c12345
}
2.char charAt(int index) 获取index位置的字符
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("hello");
System.out.println(stringBuilder.charAt(0));//h
System.out.println(stringBuilder.charAt(-1));//异常
System.out.println(stringBuilder.charAt(stringBuilder.length()));//异常
}
3.int length() 获取字符串的长度
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("hello");
System.out.println(stringBuilder.length());//5
}
4.int capacity() 获取底层保存字符串空间总的大小
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("hello");
System.out.println(stringBuilder.capacity());//21
}
5.void ensureCapacity(int mininmumCapacity) 扩容
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("hello");
System.out.println(stringBuilder.capacity());//21
stringBuilder.ensureCapacity(30);
System.out.println(stringBuilder.capacity());//44 = 21 * 2 + 2
}
6.void setCharAt(int index, char ch) 将index位置的字符设置为ch
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("hello");
stringBuilder.setCharAt(2,'a');//注意要输入char类型
System.out.println(stringBuilder);//healo
}
indexOf函数找不到相应的字符串返回-1
7.int indexOf(String str) 返回str第一次出现的位置
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaabb");
System.out.println(stringBuilder.indexOf("bb"));//2
}
8.int indexOf(String str, int fromIndex) 从fromIndex位置开始查找str第一次出现的位置
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaabb");
System.out.println(stringBuilder.indexOf("bb",4));//8
}
9.int lastIndexOf(String str) 返回最后一次出现str的位置
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("aabbccaabb"); System.out.println(stringBuilder.lastIndexOf("aa"));//6 }
原理是从后往前找
10.int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找str最后一次出现的位置
原理是从指定位置从后向前找public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("aabbccaabbaa"); System.out.println(stringBuilder.lastIndexOf("aa",5));//0 System.out.println(stringBuilder.lastIndexOf("ac",5));//-1找不到 }
11.StringBuff insert(int offset, String str) 在offset位置插入:八种基类类型 & String类型 & Object类型数据
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaabbaa");
//aaxxxbbccaabbaa
//不会覆盖原有字符,原位置字符全部往后移
System.out.println(stringBuilder.insert(2, "xxx"));
//aaxxxbbccaabbaaxxx,证明可以当追加函数使用
System.out.println(stringBuilder.insert(stringBuilder.length(), "xxx"));
//报错
//说明,要紧跟字符串末尾追加
System.out.println(stringBuilder.insert(stringBuilder.length()+1, "xxx"));
}
12.StringBuffer deleteCharAt(int index) 删除index位置字符
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaa");
System.out.println(stringBuilder.deleteCharAt(2));//aabccaa
}
13.StringBuffer delete(int start, int end) 删除[start, end)区间内的字符
注意:左开右闭[ ,)
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("aabbccaa"); System.out.println(stringBuilder.delete(2, 4));//aaccaa }
14.StringBuffer replace(int start, int end, String str) 将[start, end)位置的字符替换为str
注意:左开右闭[ ,)
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("aabbccaa"); System.out.println(stringBuilder.replace(2, 4,"xx"));//aaxxccaa System.out.println(stringBuilder.replace(2, stringBuilder.length() + 1,"xx"));//aaxx }
最后一种虽然可以指向成功但绝对不建议这么写
15.String substring(int start) 从start开始一直到末尾的字符以String的方式返回
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaa");
System.out.println(stringBuilder.substring(2));//bbccaa
System.out.println(stringBuilder.substring(stringBuilder.length()));//什么都不打印
System.out.println(stringBuilder.substring(stringBuilder.length() + 1));//报错
}
16.String substring(int start,int end) 将[start, end)范围内的字符以String的方式返回
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaa");
//这里不报错是因为左开,右闭
System.out.println(stringBuilder.substring(2, stringBuilder.length()));//bbccaa
}
17. StringBuffer reverse() 反转字符串
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaa");
//这里不报错是因为左开,右闭
System.out.println(stringBuilder.reverse());//aaccbbaa
}
18.String toString() 将所有字符按照String的方式返回
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("aabbccaa");
//StringBuilder 以 String 类型返回
System.out.println(stringBuilder.toString());//aabbccaa
}
这里要着重讲一下,原本是StringBuilder类型,要转换为String类型,就可以用toString。
注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
- String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
- StringBuilder变为String: 调用toString()方法。
四、面试题
1.
String str = new String("ab"); // 会创建多少个对象
1.会创建一个对象
String str = new String("a") + new String("b"); // 会创建多少个对象
2.a创建一个对象 + b创建一个对象 + 将他们拼接起来需要一个对象 = 3个对象
一共创建了4个对象
2.String、StringBuffer、StringBuilder的区别
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
- StringBuffer与StringBuilder大部分功能是相似的 StringBuffer采用同步处理,属于线程安全操作;
- 而StringBuilder未采用同步处理,属于线程不安全操 作