# 字符串
- String是Java定义好的一个类。定义在Java.lang包中,所以使用的时候不需要导包.
- Java中的所有字符串文字,都可以使用此类进行定义
- 字符串不可变,他们的值在创建后不能被修改
# 使用直接复制的方式,获取一个字符串对象
public class main {
public static void main(String[] args) {
String str = "Hello World";
System.out.println(str);
}
}
# 使用new的方式来获取一个字符串对象
注意
使用new关键字创建的字符串对象是一个对象属于引用数据类型
public class main {
public void main(String[] args) {
String str1 = new String("Hello World");
String str2 = "Hello World";
System.out.println(str1 == str2);//false
}
}
public class main {
public static void main(String[] args) {
//空参构造
String str1 = new String();//""
//有参构造
//传递字符串
String str2 = new String("Hello World");
System.out.println(str2);//Hello World
//传递字符数组
char[] chars = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
String str3 = new String(chars);
System.out.println(str3);//Hello World
//传递字节数组
//会将字节转换为ascii码
//应用场景 网络当中传输的数据其实都是字节信息
//一般使用字节信息转换为字符串
byte[] bytes = {97, 98, 99, 100, 101, 102, 103, 104, 105, 106};
String str5 = new String(bytes);
System.out.println(str5);//abcdefghij
}
}
# 字符串比较
# 使用==号比较
- 基本数据类型比较的是字符串值
- 引用数据类型比较的是地址值
public class main {
public void main(String[], args) {
//创建两个字符串对象
String str1 = new String("Hello World");
String str2 = "Hello World";
System.out.println(str1 == str2);//false
}
}
# 使用字符串中的equals方法比较
- equals方法比较的是字符串值
public class main {
public void main(String[], args) {
//创建两个字符串对象
String str1 = new String("Hello World");
String str2 = "Hello World";
System.out.println(str1.equals(str2));//true
}
}
# 使用equalsIgnoreCase方法比较 (忽略大小写)
- equalsIgnoreCase方法比较的是字符串值,忽略大小写
- 忽略大小写只能是英文状态下,A,a
public class main {
public void main(String[], args) {
String str1 = new String("Hello World");
String str2 = "hello world";
System.out.println(str1.equalsIgnoreCase(str2));//true
}
}
# 遍历字符串
- 遍历字符串,就是遍历字符串中的每一个字符
- 使用string中的length方法获取字符串的长度
注意
string中的length是一个方法,而数组中的length是一个属性
- 使用
str.charAt(index)获取字符串中指定位置的字符
public class main {
public void main(String[], args) {
String str = "Hello World";
for (int i = 0; i < str.length(); i++)
System.out.println(str.charAt(i));
}
}
# 截取字符串
- 使用
str.substring(start,end)截取字符串 - start表示截取的起始位置,end表示截取的结束位置,但不包含end位置的字符
public class main {
public void main(String[], args) {
String str = "Hello World";
System.out.println(str.substring(0, 5));//Hello
}
}
# 字符串替换
使用字符串的replace(oldChar,newChar)方法替换字符串中的字符
- oldChar表示要替换的字符
- newChar表示替换后的字符
public class main {
public void main(String[], args) {
String str = "Hello World";
System.out.println(str.replace('l', 'L'));//HeLlo WorLd
}
}
# 字符串练习
# 将数字转化为大写
- 将阿拉伯数字转为中文大写
- 要求加入单位
- 固定七位
- 78909 转为 零佰零拾柒万捌仟玖佰零拾玖元
public class main {
public void main(String[] args) {
//将数字转大写
//数字大写数组
String[] strMax = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
//单位数组
String[] strUnit = {"佰", "拾", "万", "仟", "佰", "拾", "元"};
int num = 78909;
//数字强制类型转换
String numToString = String.valueOf(num);
//将现有数字变为大写
StringBuilder numToStringMax = new StringBuilder();
for (int i = 0; i < numToString.length(); i++)
numToStringMax.append(strMax[numToString.charAt(i) - '0']);
//不足七位前面补零
while (numToStringMax.length() < 7)
numToStringMax.insert(0, "零");
System.out.println(numToStringMax);
//插入单位
StringBuilder result = new StringBuilder();
for (int i = 0; i < strUnit.length; i++)
result.append(numToStringMax.charAt(i)).append(strUnit[i]);
System.out.println(result);
}
}
# 字符串StringBuilder类
注意
StringBuilder类不适用于多线程的情况,有线程安全问题,如果项目存在多线程建议使用StringBuffer类
- StringBuilder类可以看做一个容器,创建之后里面的内容是可变的
- 作用:提高字符串的操作效率
- 在使用字符串进行拼接操作时,因为字符串是不可变的,所以每次拼接都会创建一个新的字符串,这样会消耗大量的内存。
# 构造方法
| 方法名 | 说明 |
|---|---|
public StringBuilder() | 创建一个空白的可变字符串StringBuilder对象 |
public StringBuilder(String str) | 根据字符串的内容,创建可变字符串StringBuilder对象 |
# 成员方法
| 方法名 | 说明 |
|---|---|
public StringBuilder append(String str)(任意类型) | 将指定的字符串追加到当前字符串的末尾 |
public StringBuilder reverse() | 反转容器中的内容 |
public StringBuilder insert(int offset,String str)(任意类型) | 将指定的字符串插入到当前字符串的指定位置 |
public StringBuilder delete(int start,int end) | 删除从start开始到end结束的子串 |
public StringBuilder replace(int start,int end,String str)(任意类型) | 用指定的字符串替换当前字符串中从start开始到end结束的子串 |
public int lastIndexOf(String str) | 返回指定子字符串在此字符串中最后一次出现处的索引 |
public int indexOf(String str) | 返回指定子字符串在此字符串中第一次出现处的索引 |
public int length() | 返回容器中字符串的长度 |
public String toString() | 将当前StringBuilder对象转换为String对象 |
public class main {
public void main(String[], args) {
//字符串StringBuilder类相关
//append方法 将指定的字符串追加到当前字符串的末尾
StringBuilder str = new StringBuilder("Hello World");
str.append("Java");//Hello WorldJava
//reverse方法
StringBuilder str1 = new StringBuilder("Hello World");
str1.reverse();
System.out.println(str1);//dlroW olleH
//insert方法 将指定的字符串插入到当前字符串的指定位置
StringBuilder str2 = new StringBuilder("Hello World");
str2.insert(5, "Java");
System.out.println(str2);//HelloJava World
//delete方法 删除当前字符串的指定位置的子字符串
StringBuilder str3 = new StringBuilder("Hello World");
str3.delete(5, 10);
System.out.println(str3);//Hellod
//replace方法 替换当前字符串的指定位置的子字符串
StringBuilder str4 = new StringBuilder("Hello World");
str4.replace(5, 10, "Java");
System.out.println(str4);//HelloJavad
//lastIndexOf方法 返回指定子字符串在此字符串中最后一次出现处的索引
String str5 = "Hello World";
System.out.println(str5.lastIndexOf("l"));//9
//indexOf方法 返回指定子字符串在此字符串中第一次出现处的索引
String str6 = "Hello World";
System.out.println(str6.indexOf("l"));//2
//length方法 返回字符串的长度
String str7 = "Hello World";
System.out.println(str7.length());//11
//toString方法 将当前字符串对象转换为字符串
StringBuilder str8 = new StringBuilder("Hello World");
System.out.println(str8.toString());//Hello World
}
}
# 字符串StringJoiner类
- StringJoiner类是jdk1.8之后出现的,作用是拼接字符串,比StringBuilder类性能更高
# 构造方法
| 方法名 | 说明 |
|---|---|
public StringJoiner(String delimiter) | 根据指定的分隔符创建StringJoiner对象 |
public StringJoiner(String delimiter,String prefix,String suffix) | 根据指定的分隔符,前缀,后缀创建StringJoiner对象 |
# 成员方法
| 方法名 | 说明 |
|---|---|
public StringJoiner add(String value) | 将指定的字符串追加到当前字符串的末尾 |
public StringJoiner setEmptyValue(String emptyValue) | 设置空值 |
public String toString() | 将当前StringJoiner对象转换为字符串 |
注意
setEmptyValue设置确定此StringJoiner的字符串表示形式且尚未添加任何元素(即当它为空时)时要使用的字符序列。- 一旦调用了
add方法,即使添加的元素对应于空字符串,StringJoiner也不再被认为是空的。
public class main {
public void main(String[], args) {
//字符串StringJoiner类相关
//add方法 将指定的字符串添加到当前字符串的末尾
StringJoiner str = new StringJoiner(",", "[", "]");
str.add("Hello").add("World");
System.out.println(str);//[Hello,World]
//setEmptyValue方法 设置空值
StringJoiner str1 = new StringJoiner("", "[", "]");
str1.setEmptyValue("空值");
System.out.println(str1);//空值
//toString方法 将当前字符串对象转换为字符串
StringJoiner str2 = new StringJoiner(",", "[", "]");
str2.add("Hello").add("World");
System.out.println(str2.toString());//[Hello,World]
}
}
# 字符串原理
# 字符串存储内存原理
- 直接复制会复用字符串常量池中的
- new出来的不会复用,而是开辟一个新的空间
# ==号比较的到底是什么
- 基本数据类型:比较的是值
- 引用数据类型:比较的是地址值
# 字符串拼接底层原理
- 在Jdk8之前,字符串直接用
+拼接,底层是调用了StringBuilder的append方法 - 每一个
+都会创建一个新的StringBuilder对象,然后调用append方法,最后将结果转换为字符串 因此效率较低 - 在Jdk8之后,会对字符串拼接进行预估,然后创建一个
StringBuilder对象调用toString方法 - 因此字符串拼接推荐直接使用
StringBuilder类或StringJoiner类
# 总结
- 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串
- 如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存
# StringBuilder提高效率原理图
- 默认会创建一个长度为16的字节数组
- 添加的内容长度小于16,则直接存储到数组中
- 添加的内容长度大于16,则会扩容(原来的容量*2+2)
- 如果扩容的容量还不够,
public class main {
public void main(String[], args) {
//无数据
StringBuilder str = new StringBuilder();
System.out.println(str.capacity());//16
System.out.println(str.length());//0
//添加abc
str.append("abc");
System.out.println(str.capacity());//16
System.out.println(str.length());//3
//扩容 16*2+2=34
str.append("defghijklmnopqrstuvwsyz");
System.out.println(str.capacity());//34
System.out.println(str.length());//26
//继续扩容 34*2+2=70
str.append("1234567890");
System.out.println(str.capacity());//70
System.out.println(str.length());//36
//扩容到一定程度则以字符串的实际长度为准
str.append("90909090909090909645645645645645645645645645645645645645666666666666666666666");
System.out.println(str.capacity());//113
System.out.println(str.length());//113
}
}