写笔记记录自己的学习记录以及巩固细节
目录
1.String类的常用方法
1.1 字符串构造
1.2 String对象的比较
1.2.1 比较两个字符串是否相等
1.2.2 比较两个字符串的大小
1.3 字符串查找
1.4 字符串的转化
1.4.1 字符串转整数
1.4.2 字符串转数字
1.4.3 大小写的转换
1.4.4 字符串与数组之间转换
1.4.5 格式化输出
1.5 字符串的替换
1.6 字符串的拆分
1.7 字符串的截取
1.8 其他操作方法
1.8.1 trim()
1.8.2 contains()
1.8.3 endWith(),startsWith()
1.9 字符串常量池
1.10 字符串的不可变性
1.11 字符串的修改
2. StringBuilder和StringBuffer
2.1 StringBuilder介绍
2.2 两者的主要区别
1.String类的常用方法
1.1 字符串构造
//两种方法一样,常用第一种
String str1 = "hello";//直接指向常量池,常量池中的哈希值指向"hello"数组
String str2 = new String("abc");//凡是new的都是在堆上开辟空间,堆上的空间再指向String的地址
//字符数组
char[] chars = {'a', 'v', 's', 'd'};
String str3 = new String(chars);
System.out.println(str3);
str1 是在常量池中创建一个新的String对象
只要是引号引出来的值都会存放在常量池中
str2 是使用了new方法在堆上开辟了一个String大小的空间
chars 是一个字符数组,直接在堆上开辟空间
str3 在堆上new了一个String对象
所有String对象中都有一个value和hash,其中value指向一个字符数组
1.2 String对象的比较
1.2.1 比较两个字符串是否相等
s1.equals(s2)方法 判断s1,s2两字符串的值是否相等,返回boolean值
s1.equalsIgnoreCase(s2) 忽略字母的大小写进行比较,返回boolean值
使用注意事项:最好把要比较的字符串放前面,可以避免空指针的风险
String string1 = new String("aaaaa");
//string1 = null;
//若使用空指针则不能 '.',会报错
System.out.println(string1.equals("aaaaa"));//若string1为null,则系统报错
//而使用"aaaaa"在前可以避免空指针异常的风险
System.out.println("aaaaa".equals(string1));
"=="比较的是两个字符串的地址是否相同
"equals"比较的是连个字符串的值是否相等
//利用new出来的字符串才算开辟新的空间
//但只要出现引号引起来的数据就会存放在在常量池中
String string1 = new String("aaaaa");
String string2 = new String("aaaaa");
//两个哈希地址一样,即都指向常量池同一个位置
System.out.println(string1.hashCode());//92567585
System.out.println(string2.hashCode());//92567585
//但 == 的结果为false,即在堆上的地址不同
System.out.println(string1 == string2);//false == 比较的是两个变量的地址是否相等
System.out.println(string1.equals(string2));//true equals比较的是具体值是否相等
有图可知,String虽然创建出了两个相同的值,但是在堆上开辟了两个不同地址的String对象,但两个String对象中的value指向的常量字符数组是同一个。
1.2.2 比较两个字符串的大小
s1.compareTo(s2) 比较s1,s2的大小,若s1 > s2返回正值,反之返回负值,若相等返回0
s1.compareToIgnoreCase(s2) 忽略大小写进行比较,返回值和compareTo()一样
//比较字符串的大小
public static void test2() {
String s1 = new String("hello");
String s2 = new String("Hello");
int ret = s1.compareTo(s2);
//忽略大小写进行比较
ret = s1.compareToIgnoreCase(s2);
if (ret > 0) {
System.out.println("s1 > s2");
} else if (ret < 0) {
System.out.println("s1 < s2");
} else {
System.out.println("s1 == s2");
}
}
1.3 字符串查找
s1.charAt(i) 返回s1中下标为i的字符
s1.indexOf('ch') 从字符串第一个字符查找,返回第一次出现’ch'字符的下标,停止查找
s1.indexOf('ch',i) 从下标为i的位置开始往后查找,返回第一次出现’ch'字符的下标
s1.indexOf("String" )从头开始查找,返回第一次出现"String"的第一个字符的下标
s1.indexOf("String",i) 同上
s1.lastIndexOf( ) 从尾部开始往前查找,用法和前面一样
//字符串中查找字符
public static void test3() {
String s1 = new String("haekasdj");
for (int i = 0; i < s1.length(); i++) {
//charAt(i) 拿到某个位置的字符
char ch = s1.charAt(i);
System.out.println(ch);
}
//indexOf(),查找,若找到返回下标,找不到返回-1
//indexOf('char') 从头开始找,遇到第一个查找的字符就结束, 返回找到字符的下标
System.out.println(s1.indexOf('a'));
//indexOf('char',i)从i下标开始找,找到第一个查找的字符就停止 ,返回该下标
System.out.println(s1.indexOf('a', 3));
//indexOf("String")从头开始找,找到第一个字符串第一个字符的下标
System.out.println(s1.indexOf("abc"));// -1
System.out.println(s1.indexOf("aek"));// 1
//从下标3开始找,返回第一个找到的字符串第一个字符的下标
System.out.println(s1.indexOf("asd",3));
//lastIndexOf()从后往前找,和以上用法相同
System.out.println(s1.lastIndexOf('a'));
}
1.4 字符串的转化
1.4.1 字符串转整数
String.valueOf()
参数转字符串
s1 = String.valueOf()
参数可以是int,char,long,float,boolean,double一类的数字
也可以是类Object
字符串 char[]
//valueOf 把参数转化为字符串
String s1 = String.valueOf(1234);
System.out.println(s1);
String s2 = String.valueOf("alskdjlkajsd");
System.out.println(s2);
//转换类时,该类中必须重写ToString方法
String s3 = String.valueOf(new Student("xiaoli", 12));
System.out.println(s3);
输出
1234
alskdjlkajsd
Student{name='xiaolei', age=12}
1.4.2 字符串转数字
Interger.parseInt()
Double.parseDouble()
//parseInt/parseDouble 字符串 转 整数
int a1 = Integer.parseInt("123123123");
System.out.println(a1);
double a3 = Double.parseDouble("12309.1203");
System.out.println(a3);
1.4.3 大小写的转换
toUpperCase() //字符串中字母全部转大写
toLowerCase() //字符串中字母全部转小写
//toUpperCase() 小写转大写 汉字不变
String s1 = "hellGtasT高";
String ret = s1.toUpperCase();
System.out.println(ret);
//toLowerCase() 大写转小写 汉字不变
ret = s1.toLowerCase();
System.out.println(ret);
输出
HELLGTAST高
hellgtast高
1.4.4 字符串与数组之间转换
toCharArray()
没有toIntArray(),因此不能用整数数组接收
String s1 = "asdasd";
//字符串转数组
char[] ch = s1.toCharArray();
System.out.println(Arrays.toString(ch));
//数组转字符串
String s2 = new String(ch);
System.out.println(s2);
//不能将字符串转换成整数数组
//int[] arr = "123123".toCharArray();
1.4.5 格式化输出
String.format() 可以像C语言那样控制格式输出
//格式化输出 String.format()
public static void test1() {
String s1 = String.format("%d,%d,%d", 2024, 4, 21);
System.out.println(s1);//2024,4,21
}
1.5 字符串的替换
s1.replace('oldChar', 'newChar') 将字符串的某个字符替换为新字符,返回一个新的字符串
s1.replace("String", "String") 将某个字符串替换为新的字符串,返回一个新的字符串
s1.replaceFirsrt() 将第一个old字符或字符串替换为新的
//将字符串中的某个字符替换,返回一个新的字符串
String s1 = "asdasdasd";
String ret = s1.replace('a', 'd');
System.out.println(ret);//dsddsddsd
//也可以将某段字符替换为任意字符串
String s2 = "asdasdasdasd";
String ret2 = s2.replace("asd", "qweqwe");
System.out.println(ret2);//qweqweqweqweqweqweqweqwe
//替换第一个字符串 或字符
String s3 = "asdasdasd";
String ret3 = s3.replaceFirst("asd", "asdfgdfgfgh");
System.out.println(ret3);//asdfgdfgfghasdasd
1.6 字符串的拆分
s1.split(char) 以某个字符为分割符,返回一个字符串数组
s1.split(char,int) 以某个字符串为分割符,限制分割为几个字符串,但不会平均分
//字符串拆分 split
public static void test3() {
//是该字符串根据某个字符分割开,返回一个字符串数组
String s1 = "zhangsan wangwu 爱上了的骄傲 zhao2";
String arr[] = s1.split(" ");
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//[zhangsan, wangwu, 爱上了的骄傲, zhao2]
//多加一个limit参数,即控制分组的数量(但不会平分,会找打第一个分隔符进行分割)
String arr_[] = s1.split(" ", 2);
System.out.println(Arrays.toString(arr_));
//[zhangsan, wangwu 爱上了的骄傲 zhao2]
// '.' 和 '\'很特殊,需要\\进行转义
String s2 = "2024.4.21";
String arr2[] = s2.split("\\.");
System.out.println(Arrays.toString(arr2));//[2024, 4, 21]
String s3 = "2024\\4\\21";
System.out.println(s3);//2024\4\21
String arr3[] = s3.split("\\\\");//表示分隔符为"\\"
System.out.println(Arrays.toString(arr3));//[2024, 4, 21]
//多个分割符,用|来分割分隔符
String s4 = "asd&gaf fdgg.asddsasd";
String arr4[] = s4.split("&| |\\.");//表示三个分隔符 & 和 ' ' 和 '.'
System.out.println(Arrays.toString(arr4));//[asd, gaf, fdgg, asddsasd]
}
1.7 字符串的截取
s1.substring(int) 从下标int作为新字符串的头,从该下标开始到尾部截取原s1,返回新字符串
s1.substring(int m,int n) 截取s1的下标[m,n),返回新字符串
//截取字符串 substring(int)
public static void test4() {
String s1 = "asddfgghjghj";
//从某个下标开始往后作为一个新字符串的第一个字符[2,tail]
String ret1 = s1.substring(2);
System.out.println(ret1);//ddfgghjghj
String ret2 = s1.substring(2, 5);//[2,5),即下标为2,3,4的字符作为新字符串
System.out.println(ret2);//ddf
}
1.8 其他操作方法
1.8.1 trim()
s1.trim() 除去s1两端的空格
//除去字符串左右两边的空格trim()
public static void test5() {
String s1 = " asdjlkw asd ";
System.out.print(s1);
System.out.println("ppppppppppppppppppp");
String s2 = " asdwasd fgdh ";
String ret2 = s2.trim();
System.out.print(ret2);
System.out.println("pppppppppppppppppp");
}
输出
asdjlkw asd ppppppppppppppppppp
asdwasd fgdhpppppppppppppppppp
1.8.2 contains()
s1.contains("String") 判断s1中是否有String片段 ,返回boolean值
//判断字符串中是否包含 某一段字符串contains,返回类型为boolean
public static void test6() {
String s1 = " hello asdkhello";
System.out.println(s1.contains("hello"));//true
}
1.8.3 endWith(),startsWith()
s1.endWith("String") 判断s1是否以String结尾
s1.startsWith("String") 判断s1是否以String开头 返回boolean值
//判断字符串是否是以某段字符串结尾 或开头的 返回boolean
public static void test7() {
String s1 = "asd sdfjlf kkk";
System.out.println(s1.endsWith("kkk"));//true
System.out.println(s1.startsWith("asd"));//true
}
1.9 字符串常量池
凡是出现在双引号中的值,都会被保存在字符串常量池中。
凡是使用new关键字开辟的新空间都是在堆上。
如果没使用new开辟空间,那么对于常量池所存在的数据,有且只能有一个,也就是多个变量可以指向同一个空间
双引号中的数据 系统会先检查常量池中是否有该数据 如果有就直接引用 如果没有就会把该常量放进去 即在常量池中只会维护一个“abcd"对象
public static void test1() {
//双引号中的数据 系统会先检查常量池中是否有该数据
//如果有就直接引用 如果没有就会把该常量放进去
//即在常量池中只会维护一个“aaaaa"对象
String s1 = "aaaaa";
String s2 = "aaaaa";
//在堆上开辟空间 这个堆上的地址中的value指向的是常量池中的数据
String s3 = new String("aaaaa");
String s4 = new String("aaaaa");
System.out.println(s1 == s2);//true
System.out.println(s3 == s4);//false //堆上的地址不一样
System.out.println(s1 == s3);//false
}
1.10 字符串的不可变性
String类中的字符实际保存在内部维护的value字符数组中
1. String类被final修饰,表名该类不能被继承
2. value被final修饰,表示value自身的值不能改变,既不能引用其它字符数组,但是其引用空间的内容可以被修改
3. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
1.11 字符串的修改
字符串的修改实际上是创建了新的对象
在循环中进行字符串拼接时,String在每次拼接时都是创建新的对象,很费时间
//在循环中进行字符串拼接时,String在每次拼接时都是创建新的对象,很费时间
//StringBuffer 和 StringBuilder是根据原来对象进行拼接
//在循环拼接字符串最好使用StringBuffer 和 StringBuilder
public static void test3() {
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 100000; i++) {
s += i;
}
long end = System.currentTimeMillis();
System.out.println(end - start);//3019
start = System.currentTimeMillis();
StringBuffer s1 = new StringBuffer("");
for (int i = 0; i < 100000; i++) {
s1.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);//3
start = System.currentTimeMillis();
StringBuilder s2 = new StringBuilder();
for (int i = 0; i < 100000; i++) {
s2.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);//2
}
2. StringBuilder和StringBuffer
2.1 StringBuilder介绍
//String拼接的实质
public static void test4() {
String s1 = "abcd";
//循环内的相当于 s1 += i
//即String的拼接每次都会 创建一个新的对象以及两次拼接和一次转换
for (int i = 0; i < 100; i++) {
StringBuilder sb = new StringBuilder();
sb.append(s1);
sb.append(i);
s1 = sb.toString();//类型转换
}
System.out.println(s1);
//以上代码可以简化为如下
StringBuilder stringBuilder = new StringBuilder("abcd");
for (int i = 0; i < 100; i++) {
stringBuilder.append(i);
}
System.out.println(stringBuilder);
}
2.2 两者的主要区别
//StringBuffer 和 StringBuilder
public static void test5() {
StringBuilder stringBuilder = new StringBuilder("asdfghjkl");
//逆置字符串 String则没有这个方法
stringBuilder.reverse();
System.out.println(stringBuilder);
}