String的常用方法
比较方法
s1.equals(s2) 要区分大小写比较两个字符串的内容是否相同
s1.equalsIgnoreCase(s2) 不区分大小写比较两个字符串的内容是否相同
s1.compareTo(s2) 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。如果前k个字符相等(k为两个字符长度最小值),返回值等于两个字符串长度差值
s1.compareToIgnoreCase(s2)同上面一样,只不过不区分大小写
s1.intern() 如果字符串s在字符串常量池中存在对应字面量,则intern()方法返回该字面量的地址;如果不存在,则创建一个对应的字面量,并返回该字面量的地址
例如:
public static void main(String[] args) {
String s1 = new String("字符串");
String s2 = "字符串";
System.out.println(s2 == s2.intern());
System.out.println(s1 == s1.intern());
System.out.println(s1.intern() == s2.intern());
}
结果:true、false、true
解释:
s2.intern()返回的是常量池中"字符串"的地址0x3344
s2指向的是常量池中的地址0x3344
s1.intern()返回的是常量池中"字符串"的地址0x3344
s1.intern()指向的是堆中的地址0x1122
查找方法
indexOf(int ch) 返回字符在字符串中第一次出现的位置,如果该字符不在字符串中,则返回-1
lastindexOf(int ch) 返回字符在字符串中最后一次出现的位置,如果该字符不在字符串中,则返回-1
charAt(int index) 返回字符串中特定位置的字符,如果index为负或者越界,抛出异常
字符串转化
s1 = String.valueof(s2) 将数值s2转化为字符串
s1 = Integer.parselnt(s2) 将字符串s2转化为数值
s1.toUpperCase() 将小写字符串转换成大写字符串
s1.toLowerCase() 将大写字符串转换成小写字符串
char[] ch = s.toCharArray() 将字符串s转换为字符数组ch
s = String.format("%d-%d-%d",2019,9,14) 格式化字符串
字符串替换
str.replaceAll(String A,String B) 将字符串里面的字符串A全部替换为字符串B
str.replaceFrist(String A,String B) 将字符串里面的首个字符串A替换为字符串B
str.replace(char A,char B) 将字符串里面的A,全部替换为B
字符串拆分
String[] result = str.split("A") 将字符串str按照字符串A拆分
String str = "hello world hello bit";
String[] result = str.split(" ");
for (String s:result) {
System.out.println(s);
}
String[] split(String regex,int limit) 将字符串以指定的格式,拆分为limit组
String str = "hello world hello bit";
String[] result = str.split(" ",2);
for (String s:result) {
System.out.println(s);
}
注意:
1.字符"|","*","+"在拆分的时候,前面都要加上"\\"
2.如果是"\",那么就得写成"\\\\"
3.如果一个字符中有多个分隔符,就可以用"|"作为连字符
for(int i = 0;i< result.length;i++){
String[] temp = result[i].split("=");
System.out.println(temp[0]+"="+temp[1]);
}
字符串截取
String substring(int beginIndex) 从指定索引截取到尾巴
String substring(int beginIndex,int endIndex) 截取部分类容
其他操作
String trim() 去掉字符串中的左右空格,保留中间空格
int len = s1.length() 计算字符串长度
String s1 = concat(String s2) 将指定的字符串连接在字符串的末尾
String s1 = "宝玉";
s1 = s1.concat("林黛玉").concat("薛宝钗");
System.out.println(s1);//宝玉林黛玉薛宝钗
String的构造方法
方式一:直接赋值String s = "wanglei";
方式二:调用构造器String s = new String("西华大学");
两种创建String对象的区别
直接赋值法是现从常量池查看是否有“wanglei”数据空间,如果有,直接指向;如果没有则重新创建,然后指向,s最终指向的是常量池的空间地址。
使用构造器方法是先在堆中创建空间,里面维护了value属性,指向常量池的"西华大学"空间,如果常量池没有“西华大学”,则重新创建,如果有,直接通过value指向。s指向的是堆中的空间地址。
StringBuffer的构造方法
StringBuffer jack = new StringBuffer("jack");
StringBuffer和String的相互转换
String hobit = "打篮球";
//方式一:使用构造器
StringBuffer stringBuffer = new StringBuffer(hobit);
//方式二:使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(hobit);
//StringBuffer--》String
StringBuffer buffer = new StringBuffer("四川西华大学");
//方式一:使用StringBufferr提供的toString方法
String s = buffer.toString();
//方式二:使用构造起来搞定
String s1 = new String(buffer);
StringBuffer的常用方法
s.append(); 增加
s.delete(start,end); 删除索引为>=start&&<end处的字符
s.replaxe(start,end,"A") 将索引为>=start&&<end处的字符改为A
s.insert(index,"A") 在索引为index的位置插入"A",原来索引为index的类容自动后移
StringBuffer animal = new StringBuffer("小猫");
//增
System.out.println(animal.append(','));//小猫,
System.out.println(animal.append("正在跳舞 "));//小猫,正在跳舞
System.out.println(animal.append("小狗").append(',').append("正在睡觉"));
//删
//删除的时候是前闭后开的
String res = new String(animal.delete(2, 4));
System.out.println(res);
System.out.println(animal);
//改
//修改的时候也是前闭后开的
System.out.println(animal.replace(0, 2, "小鸟"));//小鸟,正在跳舞 小狗,正在睡觉
//插入
System.out.println(animal.insert(0, "愤怒的"));//愤怒的小鸟,正在跳舞 小狗,正在睡觉,在索引为0的位置插入“愤怒的”原来索引为0的内容开始后移
StringBuilder的常用方法
s1.setCharAt(int index,char ch) 将index位置的字符设置为ch
s1.indexOf(String str,int formIndex) 从fromIndex位置开始查找str第一次出现的位置
s1.deleteCharAt(int index) 删除index位置字符
s1.reverse() 字符串反转
其他很多方法都和String、StringBuffer一样
String的一些细节
1.String底层是通过一个char类型的value[]数组存储字符的,而value[]具有private、final两个属性。
被final修饰,代表字符串是不可变的字符序列,说明String不能被其他的类继承。String不可变的另一个原因是因为value[]被private修饰,外部无法改变数组里面的类容,而且String也没有提供修改字符数组value[]的方法。
2.虽然说字符串不可变,但是我们在给一个字符串变量赋值后却能给它赋其他的值,而且输出的结果是最后一次修改的值,如下:
String s = "Hello";
s = "";
System.out.println(s);
结果是:
这里就要解释一下了,s被两次赋值,说明在常量池中创建了两个对象 ,而第一次s指向的是“Hello”,第二次指向的是“”。在变量输出结果是以最后一次修改为准。我们认为s被修改了,但是原来的字符串“Hello”却没有发生改变,只要修改没有影响到源数据,就说明String具有不可变性。同样在获取底层字符数组时,都是复制一个原数组返回,,修改数组也是拿复制的数组进行修改,底层数组不会受到影响。
3.既然value[]被private修饰了,不可以更改数组里面的类容了,为什么还要用final修饰呐,final是在保证变量在首次被赋值后,后面使用也无法修改变量里面的类容。
4.value是一个final类型,不可以修改,即value不能指向新的地址,但是单个字符类容是可以变化的,但是字符串不可修改的另一个原因是因为value被private修饰
5.字符串不可变的优点:1. 保证常量池复用的可靠 2. 哈希码只需要计算一次 3. 不可变的是线程安全的。
6.字符串常量相加,看的是常量池,字符串类型的变量相加是在堆中。
String a = "Hello";
String b = "World";
String c = "Hello"+"World";
String d = "HelloHorld";
String e = a+b;
System.out.println(c==d);//true
System.out.println(c==e);//false
StringBuffer的一些细节
1.StringBuffer是线程安全的可变字符序列,可以对字符串类容进行增删(private char[])。StringBuffer的线程安全在于很多方法都被synchronized修饰,也就是说无论哪个线程运行到这个方法的时候都要检查有没有其他线程在使用这个方法,有的话要等正在使用synchronized方法的线程B运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。
2.String和StringBuffer的区别:String保存的是字符常量,里面的值不能被修改,每次String类的更新更新的是地址,效率较低;StringBuffer保存的是字符串变量,里面的值可以更改,每次更新更新的是字符串里面的类容,效率较高。
3.其他很多方法和String一样
StringBuilder的一节
1.StringBuilder是一个StringBuffer的简易替换,因为它在单线程的情况下使用速度很快。但是StringBuild不是线程安全的,不能在多线程下使用。
String、StringBuffer、StringBuild的使用选择
- 如果字符串存在大量的修改操作,一般使用StringBuffer、StringBuilder
- 如果字符串存在大量的修改操作,并在单线程下,那么选择StringBuilder
- 如果字符串存在大量的修改操作,并在多线程下,那么选择StringBuffer
- 如果字符串很少修改,被多个对象引用,使用String