1. String 对象的创建
String对象的创建有两种方式。
第1 种方式就是我们最常见的创建字符串的方式:
String str1 = "8/24";
第 2 种方式是对象实例化的方式,使用new
关键字,并将要创建的字符串作为构造参数:
String str2 = new String("8/25");
如果调用 String 类的无参构造方法,则会创建一个空字符串:
String str3 = new String();
这种方式很少使用。
2. 获取字符串长度
可以使用length()
方法来获取字符串的长度。例如:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "8/24";
int a = str1.length();
System.out.println(a);
}
}
运行结果:
4
3. 字符串查找
3.1 获取指定位置字符
可以使用char charAt(int index)
方法获取字符串指定位置的字符。它接收一个整型的index
参数,指的是索引位置,那什么是索引位置呢?例如,有一字符串I love Java
,其每个字符的索引如下图所示:
可以从图示中看出,索引下标从0
开始。假如我们要获取字符C
,则为方法传入参数2
即可:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "ABCDEFG";
char a = str1.charAt(4);
System.out.println(a);
}
}
运行结果:
E
3.2 查找字符串位置
这里介绍查找字符串位置的两个方法:
-
indexOf()
获取字符或子串在字符串中第一次出现的位置。 -
lasIndexOf()
获取字符或子串在字符串中最后一次出现的位置。
这里的子串指的就是字符串中的连续字符组成的子序列。例如,字符串
Hello
就是字符串Hello Java
的子串。
indexOf()
1 获取字符在字符串中第一次出现的位置:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "ABCDEFG";
int a = str1.indexOf('G');
System.out.println("字符A在字符串str1第一次出现的位置为:"+ a);
}
}
字符A在字符串str1第一次出现的位置为:6
2 获取子串在字符串中第一次出现的位置:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I just poor boy,I needn`t sympathy";
int a = str1.indexOf('I');
System.out.println("字串I在字符串str1第一次出现的位置为:"+ a);
}
}
字符I在字符串str1第一次出现的位置为:0
lastIndexOf()
1 获取字符在字符串中最后一次出现的位置:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I just poor boy,I needn`t sympathy";
int a = str1.lastIndexOf("I");
System.out.println("字串I在字符串str1最后一次出现的位置为:"+ a);
}
}
字串I在字符串str1最后一次出现的位置为:16
2 获取子串在字符串中最后一次出现的位置:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I love LYF and I love PYY";
int a = str1.lastIndexOf("I love");
System.out.println("子串I love在字符串str1最后一次出现的位置为:"+ a);
}
}
运行结果:
子串I love在字符串str1最后一次出现的位置为:15
需要特别注意的是,以上方法的参数都是区分大小写的。如果你找了个不存在的,上述方法都会返回一个整型值:-1
。我们来看以下示例:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I love LYF and I love PYY";
int a = str1.lastIndexOf("QQ");
System.out.println("子串QQ在字符串str1最后一次出现的位置为:"+ a);
}
}
子串QQ在字符串str1最后一次出现的位置为:-1
可以看到结果是-1
4. 字符串截取
字符串的截取也称为获取子串
可以使用substring()
方法来获取子串
String类中有两个重载的实例方法:
-
String substring(int beginIndex)
获取从beginIndex
位置开始到结束的子串。 -
String substring(int beginIndex, int endIndex)
获取从beginIndex
位置开始到endIndex
位置的子串(不包含endIndex
位置字符)
关于这两个方法的使用,我们来看一个实例:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I just poor boy,I need no sympathy";
String a = str1.substring(15);
String b = str1.substring(8,12);
System.out.println("从15到最后的字符串"+ a);
System.out.println("从8到12的字符串"+ b);
}
}
运行结果:
从15到最后的字符串,I need no sympathy
从8到12的字符串oor
要特别注意,方法签名上有两个参数的substring(int beginIndex, int endIndex)
方法
截取的子串不包含endIndex
位置的字符。
5. 字符串切割
5.1 切割为字串数组
String[] split(String regex)
方法可将字符串切割为子串,其参数regex
是一个正则表达式分隔符,返回字符串数组。
例如,我们使用空格作为分隔符来切割I just poor boy,I need no sympathy
字符串,结果将返回含有7个元素的字符串数组:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "I just poor boy,I need no sympathy";
String[] a = str1.split(" ");
for (String index : a) {
System.out.print(index+'\t');
}
}
}
I just poor boy,I need no sympathy
注意,有几种特殊的分隔符:*
^
:
|
.
\
,要使用转义字符转义。例如:
String[] a = str2.split("\\*");
String[] b = str3.split("\\\\");
String[] c = str4.split("\\|");
String[] split(String regex, int limit)
其第二个参数limit
用以控制正则匹配被应用的次数
5.2 切割为 byte 数组
在实际工作中,网络上的数据传输就是使用二进制字节数据。因此字符串和字节数组之间的相互转换也很常用。
我们可以使用getBytes()
方法将字符串转换为byte
数组。例如:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "ABCD";
byte[] a = str1.getBytes();
for (byte index : a) {
System.out.print(index + "\t");
}
}
}
运行结果:
65 66 67 68
将字节数组转换为字符串的方法很简单,直接实例化一个字符串对象,将字节数组作为构造方法的参数即可:
// 此处的ascii为上面通过字符串转换的字节数组
String s = new String(ascii);
6. 字符串大小写转换
字符串的大小写转换有两个方法:
-
toLowerCase()
将字符串转换为小写 -
toUpperCase()
将字符串转换为大写
我们来看一个实例:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "ABCD";
String a = str1.toLowerCase();
System.out.println("小写:"+a);
String b = str1.toUpperCase();
System.out.println("大写:"+b);
}
}
运行结果:
小写:abcd
大写:ABCD
试想,如果想把字符串HELLO world
中的大小写字母互换,该如何实现呢?
这里可以结合字符串切割方法以及字符串连接来实现:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "AB CD";
//先切割位数组
String[] a = str1.split(" ");
//通过索引,分别变为大写和小写
String result = a[0].toLowerCase() + " " + a[1].toUpperCase();
System.out.println(result);
}
}
运行结果:
ab CD
当然,实现方式不止一种
7. 字符串比较
String
类提供了boolean equals(Object object)
方法来比较字符串内容是否相同,返回一个布尔类型的结果。
需要特别注意的是,在比较字符串内容是否相同时,必须使用equals()
方法而不能使用==
运算符。我们来看一个示例:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
String str1 = "AB CD";
String str2 = new String("AB CD");
String str3 = "AB CD";
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
System.out.println(str1==str3);
}
}
运行结果:
false
true
true
代码中三个字符串str1
,str2
和str3
的内容都是AB CD
,因此使用equals()
方法对它们进行比较,其结果总是为true
。
注意观察执行结果,其中使用==
运算符比较str1
和str2
的结果为true
,但使用==
运算符比较的str1
和str3
的结果为false
。
这是因为==
运算符比较的是两个变量的地址而不是内容。
我用图来解释一下!!!
1.当执行String str1 = "AB CD;"
语句时,会在内存的栈空间中创建一个str1
,在常量池中创建一个"AB CD",并将str1
指向hello
。
当执行String str2 = "hello";
语句时,栈空间中会创建一个str2
,由于其内容与str1
相同,会指向常量池中的同一个对象。所以str1
与str2
指向的地址是相同的
这就是==
运算符比较str1
和str2
的结果为true
的原因。
2.当执行String str3 = new String("hello");
语句时,使用了new
关键字创建字符串对象,由于对象的实例化操作是在内存的堆空间进行的,此时会在栈空间创建一个str3
,在堆空间实例化一个内容为hello
的字符串对象,并将str3
地址指向堆空间中的hello
,这就是==
运算符比较str1
和str3
的结果为false
的原因。
8. 小结
我们介绍了 Java String
类的常用方法:
- 使用
length()
方法可以获取字符串长度; - 使用
charAt()
、indexOf()
以及lastIndexOf()
方法可以对字符串进行查找; -
substring()
方法可以对字符串的进行截取,split()
、getBytes()
方法可以将字符串切割为数组; -
toLowerCase()
和toUpperCase()
方法分别用于大小写转换,使用equals()
方法对字符串进行比较,这里要注意,对字符串内容进行比较时,永远都不要使用==
运算符。
这些方法大多有重载方法,实际工作中,要根据合适的场景选用对应的重载方法。!!!
奥里给就完了
1. StringBuilder 概述
1.1 什么是 StringBuilder
与 String
相似,StringBuilder
也是一个与字符串相关的类
Java 官方文档给 StringBuilder
的定义是:可变的字符序列。
1.2 为什么需要 StringBuilder
在 Java 字符串的学习中,我们知道了字符串具有不可变性,当频繁操作字符串时候,会在常量池中产生很多无用的数据
而 StringBuilder
与 String
不同,它具有可变性。相较 String
类不会产生大量无用数据,性能上会大大提高。
因此对于需要频繁操作字符串的场景,建议使用 Stringbuilder
类来代替 String
类。
2. StringBuffer 概述
2.1 定义
了解了 StringBuilder
类 ,StringBuffer
也是不得不提的一个类,Java 官方文档给出的定义是:线程安全的可变字符序列。
2.2 与前者的区别
StringBuffer
是 StringBuilder
的前身,在早期的 Java
版本中应用非常广泛,它是 StringBuilder
的线程安全版本(线程我们将在后面的小节中介绍),但实现线程安全的代价是执行效率的下降。
你可以对比 StringBuilder
和 StringBuffer
的接口文档,它们的接口基本上完全一致。为了提升我们代码的执行效率,在如今的实际开发中 StringBuffer
并不常用。
3. StringBuilder 的常用方法
3.1 构造方法
StringBuilder
类提供了如下 4 个构造方法:
-
StringBuilder()
构造一个空字符串生成器,初始容量为 16 个字符; -
StringBuilder(int catpacity)
构造一个空字符串生成器,初始容量由参数 capacity
指定; -
StringBuilder(CharSequence seq)
构造一个字符串生成器,该生成器包含与指定的 CharSequence
相同的字符。; -
StringBuilder(String str)
构造初始化为指定字符串内容的字符串生成器。
其中第 4 个构造方法最为常用,我们可以使用 StringBuilder
这样初始化一个内容为 hello
的字符串:
package com.caq.oop.demo08; public class Test { public static void main(String[] args) { StringBuilder str = new StringBuilder("8/24"); } }
3.2 成员方法
StringBuilder
类下面也提供了很多与 String
类相似的成员方法,以方便我们对字符串进行操作。下面我们将举例介绍一些常用的成员方法。
3.2.1 字符串连接
可以使用 StringBuilder
的 StringBuilder append(String str)
方法来实现字符串的连接操作。
我们知道,String
的连接操作是通过 +
操作符完成连接的:
String str1 = "Hello"; String str2 = "World"; String str3 = str1 + " " + str2;
如下是通过 StringBuilder
实现的字符串连接示例:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
StringBuilder str = new StringBuilder("8/24");
str.append(" ");
str.append("world");
System.out.println(str);
}
}
运行结果:
8/24 world
由于 append()
方法返回的是一个 StringBuilder
类型,我们可以实现链式调用。例如,上述连续两个 append()
方法的调用语句,可以简化为一行语句:
//链式调用
str.append(" ").append("world");
如果你使用 IDE
编写如上连接字符串的代码,可能会有下面这样的提示(IntelliJ idea 的代码截图):
提示内容说可以将 StringBuilder
类型可以替换为 String
类型,也就是说可以将上边地代码改为:
String str = "8/24" + " " + "world";
这样写并不会导致执行效率的下降,这是因为 Java 编译器在编译和运行期间会自动将字符串连接操作转换为 StringBuilder
操作或者数组复制,间接地优化了由于 String
的不可变性引发的性能问题。
值得注意的是,append()
的重载方法有很多,可以实现各种类型的连接操作。例如我们可以连接 char
类型以及 float
类型,实例如下:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
StringBuilder str = new StringBuilder("zs的身高是");
str.append(':').append(172.5f);
System.out.println(str);
}
}
运行结果:
zs的身高是:172.5
上面代码里连续的两个 append()
方法分别调用的是重载方法 StringBuilder append(char c)
和 StringBuilder append(float f)
。
3.2.2 获取容量
可以使用 int capacity()
方法来获取当前容量,容量指定是可以存储的字符数(包含已写入字符),超过此数将进行自动分配。注意,容量与长度(length)不同,长度指的是已经写入字符的长度。
例如,构造方法 StringBuilder()
构造一个空字符串生成器,初始容量为 16 个字符。我们可以获取并打印它的容量,实例如下:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
// 调用StringBuilder的无参构造方法,生成一个str对象
StringBuilder stringBuilder = new StringBuilder();
System.out.println(stringBuilder.capacity());
for (int i = 0; i < 17; i++) {
stringBuilder.append(i);
}
System.out.println(stringBuilder.capacity());
}
}
运行结果:
16 34
3.2.3 字符串替换
可以使用 StringBuilder replace(int start, int end, String str)
方法,来用指定字符串替换从索引位置 start
开始到 end
索引位置结束(不包含 end
)的子串。实例如下:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
// 调用StringBuilder的无参构造方法,生成一个str对象
StringBuilder stringBuilder = new StringBuilder("Hello monkey");
// 调用字符串替换方法,将 monkey 替换为 Jack
stringBuilder.replace(6,12, "Jack");
System.out.println(stringBuilder);
}
}
在IDEA里,是有提示的
运行结果:
Hello Jack
也可使用 StringBuilder delete(int start, int end)
方法,先来删除索引位置 start
开始到 end
索引位置(不包含 end
)的子串,再使用 StringBuilder insert(int offset, String str)
方法,将字符串插入到序列的 offset
索引位置。同样可以实现字符串的替换,例如:
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
// 调用StringBuilder的无参构造方法,生成一个str对象
StringBuilder stringBuilder = new StringBuilder("Hello monkey");
stringBuilder.delete(6,12);
//从第6位开始插入,内容是Jack
stringBuilder.insert(6,"Jack");
System.out.println(stringBuilder);
}
}
3.2.4 字符串截取
可以使用 StringBuilder substring(int start)
方法来进行字符串截取,例如,我们想截取字符串的第7到第9个字符,实例如下:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
// 调用StringBuilder的无参构造方法,生成一个str对象
StringBuilder stringBuilder = new StringBuilder("Hello monkey");
String str = stringBuilder.substring(7, 9);
System.out.println(str);
}
}
运行结果:
on
3.2.5 字符串反转
可以使用 StringBuildr reverse()
方法,对字符串进行反转操作,例如:
实例演示
package com.caq.oop.demo08;
public class Test {
public static void main(String[] args) {
// 调用StringBuilder的无参构造方法,生成一个str对象
StringBuilder stringBuilder = new StringBuilder("Hello monkey");
System.out.println(stringBuilder.reverse());
}
}
运行结果:
yeknom olleH
4. 小结
今天我们介绍了 Java 的 StringBuilder
类,它具有可变性,对于频繁操作字符串的场景,使用它来代替 String
类可以提高程序的执行效率;
也知道了 StringBuffer
是 StringBuilder
的线程安全版本