目录
2 StringBuilder 和 StringBuffer
2.1 StringBuilder 和 StringBuffer 的区别
2.2 StringBuilder、StringBuffer 和 String 比较
1 常用方法
1.1 字符串构造
String 是字符串类型
String 类提供的构造方式非常多,常用的就以下三种:
① 使用常量串构造
String s1 = "hello bit";
System.out.println(s1);
② 直接 newString 对象
String s2 = new String("hello bit");
System.out.println(s2);
③ 使用字符数组进行构造
char[] array = {'h','e','l','l','o','b','i','t'};
String s3 = new String(array);
System.out.println(s3);
其它构造方法
从0位置开始偏移1个输出 a
从0位置开始偏移2个输出 ab
从1位置开始偏移2个输出 bc
1.2 字符串包含的成员
① 注意:String 是引用类型,内部并不存储字符串本身,在 String 类的实现源码中,String 类实例变量如下:
System.out.println(s1.length());
// 获取字符串长度
// 打印"hello"字符串(String对象)的长度也可以直接某一字符串. length()
System.out.println("hello".length());
结果:5
System.out.println(s1.isEmpty());
// 如果字符串长度为0,返回true,否则返回 false
② 在 Java 中 “ ” 引起来的是 String 类型对象
1.3 String 对象的比较
① == 比较(两个引用变量比较的是地址)
注意:对于内置类型, == 比较的是变量中的值;对于引用类型 == 比较的是引用中的地址
② 比较内容(boolean equals(Object anObject))
String 类重写了父类 Object 中 equals 方法, Object 中 equals 默认按照 == 比较, String 重写 equals 方法后,按照如下规则进行比较,比如: s1.equals(s2)
③ 比较大小(int compareTo(String s))
④ 忽略大小写比较大小(int compareToIgnoreCase(String str))
1.4 字符串查找
① char charAt(int index) (通过下标返回字符)
返回 index 位置上字符,如果 index 为负数或者越界,抛出 IndexOutOfBoundsException 异常
一个一个字符串进行打印
② int indexOf(int ch) (通过字符返回下标)
返回 ch 第一次出现的位置,没有返回-1
当出现两个相同字符串时默认从头到后(第一个字符串出现的位置)
③ int indexOf(int ch, int fromIndex) (从指定位置开始查找)
从 fromIndex 位置开始找 ch 第一次出现的位置,没有返回-1
从3位置开始找,打印结果为:3
从指定位置查找字符串出现的位置
从3位置开始找,打印结果为:5
④ int lastIndexOf(int ch) (通过下标倒着找字符)
从后往前找,返回 ch 第一次出现的位置,没有返回-1
结果:5
⑤ int lastIndexOf(int ch, int fromIndex) (从指定位置倒着往回找)
从 fromIndex 位置开始找,从后往前找 ch 第一次出现的位置,没有返 回-1
从4位置开始倒着往回找,结果为:2
1.5 转化
1.5.1 数值和字符串转化
ValueOf 中不管传任何数据都会变成字符串
也可以字符串转数字
1.5.2 大小写转化
① toUpperCase (小写变大写,原来大写的不动)
转变大小写需要进行接收,是一个新对象
未接收则是原来的对象
② toLowerCase (大写变小写,原来小写的不动)
1.5.3 字符串转数组
数组转字符串
1.5.4 格式化
此处 %d 相当于一个占位符
1.6 字符串替换
replace(有两种)
两个 replace 里面的参数不一样,一个两个都是 char 类型,还有一个两个都是 charSequence
String 类在定义时实现了 charSequence 接口,意味着对于 charSequence 接口本身来说能接收String 类型数据
对 String 本身修改都是产生新的对象的(字符串的不可变性)
另外两个与 replace 有关的
① replaceFrist (只对第一次出现的进行修改)
② replaceAll (替换所有指定内容)
1.7 字符串拆分
以空格为分割拆分
以空格分开最多分两组
特殊情况
①
修改后
②
③
也可以进行两次分割(在第一次分割基础上进行第二次分割)
注意
1. 字符“.”,“|”,“*”,“+”都得加上转义字符,前面加上 “\\”
2. 而如果是 “\\” ,那么就得写成 “\\\\”
3. 如果一个字符串中有多个分隔符,可以用“|”作为连字符
1.8 字符串截取
1.9 其他操作方法
1.10 字符串的不可变性
String 类不能修改的主要原因是:String 类功能是私有的
String 是一种不可变对象,字符串中的内容是不可改变,字符串不可被修改,是因为:
① String 类在设计时就是不可改变的,String 类实现描述中已经说明了
以下来自 JDK1.8 中 String 类的部分实现:
String 类中的字符实际保存在内部维护的 value 字符数组中,该图还可以看出:
1. String 类被 final 修饰,表明该类不能被继承
2. value 被修饰被 final 修饰,表明 value 自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改
② 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
纠正:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变,这种说法是错误的,不是因为 String 类自身,或者其内部 value 被 final 修饰而不能被修改
final 修饰类表明该类不想被继承,final 修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的
为什么 String 要设计成不可变的?(不可变对象的好处是什么?)
1. 方便实现字符串对象池,如果 String 可变,那么对象池就需要考虑写时拷贝的问题了
2. 不可变对象是线程安全的
3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中
那如果想要修改字符串中内容,该如何操作呢?
1.11 字符串修改
注意:尽量避免直接对 String 类型对象进行修改,因为 String 类是不能修改的,所有的修改都会创建新对象,效率非常低下
如果要修改建议尽量使用 StringBuffer 或者 StringBuilder
String、StringBuffer、StringBuilder 对 String 类型对象进行修改,由于 String 类不能修改,所有的修改都会创建新对象,每次返回的对象都不一样,不断地创建对象销毁对象,效率非常低下,而 StringBuffer、StringBuilde 都在 append 拼接后指向同一个对象
String、StringBuffer、StringBuilder 对 String 类型对象进行修改前后之间的时间对比
2 StringBuilder 和 StringBuffer
由于 String 不可更改特性,为了方便字符串的修改, Java 中又提供 StringBuilder 和 StringBuffer 类,这两个类大部分功能是相同的
2.1 StringBuilder 和 StringBuffer 的区别
StringBuffer 的 append 方法
StringBuilder 的 append 方法
StringBuilder 和 StringBuffer 中 append 内容没什么区别,都是返回 this,区别在于方法旁边的关键字
线程安全类似于一间厕所有人进去后就上了锁,即同一时间只有一个线程可以执行此方法
每次开锁和上锁都需要耗费资源,StringBuffer 是线程安全的,也意味着在多线程情况下虽然安全,但是效率很低,频繁的开锁上锁对资源是消耗的
2.2 StringBuilder、StringBuffer 和 String 比较
StringBuilder 和 StringBuffer 这两个类包含了一些 String 没有的方法,它的功能进一步扩大
StringBuff append(String str)
在尾部追加,相当于 String的+=,可以追加(追加:即尾插):boolean、char、char[]、 double、float、int、long、Object、String、StringBuff 的变量
StringBuff insert(int offset, String str)
在 offset 位置插入:八种基类类型 & String类型 & Object类型数据
public class StringBufferInsertExample {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer("Hello World!");
buffer.insert(6, "Beautiful ");
System.out.println(buffer.toString()); // 输出: Hello Beautiful World!
}
}
StringBuffer deleteCharAt(int index)
删除index位置字符
StringBuffer delete(int start, int end)
删除[start, end)区间内的字符
StringBuffer replace(int start, int end, String str)
将[start, end)位置的字符替换为str
StringBuffer reverse()
反转字符串:对字符串进行逆置
以 String 方法返回的方法
String 和 StringBuilder、StringBuffer 类不能直接转换,要想互相转换,可以采用如下原则:
String 变为 StringBuilder 或 StringBuffer:利用 StringBuilder 的构造方法或 append() 方法
StringBuilder 变为String:调用 toString() 方法
补充
String、StringBuffer、StringBuilder 的区别
String 的内容不可修改,StringBuffer 与 StringBuilder 的内容可以修改,包含的方法也不一样
StringBuffer 与 StringBuilder 大部分功能是相似的
StringBuffer 采用同步处理,属于线程安全操作
StringBuilder 未采用同步处理,属于线程不安全操作
3 试题
① 第一个只出现一次的字符
② 最后一个单词的长度
③ 检测字符串是否为回文
④ 字符串相加
⑤ 字符串转整形数字
方法一:使用Integer.parseInt()方法:
方法二:定义了一个 stringToInt 方法,它尝试将输入的字符串转换为整数。如果字符串不是一个有效的整数表示,则返回0。代码还处理了溢出情况,确保返回的整数在 Java 的 Integer 类型的范围内
public class StringToInteger {
public static void main(String[] args) {
String str = "1234";
int num = stringToInt(str);
System.out.println("转换后的整数为: " + num);
}
public static int stringToInt(String str) {
if (str == null) {
return 0;
}
int res = 0;
boolean isPositive = true;
for (int i = 0; i < str.length(); i++) {
if (i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')) {
isPositive = str.charAt(i) == '+' ? true : false;
continue;
}
if (str.charAt(i) < '0' || str.charAt(i) > '9') {
return 0;
}
res = res * 10 + (str.charAt(i) - '0');
if (res > Integer.MAX_VALUE) {
return isPositive ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
}
return isPositive ? res : -res;
}
}