在 C 语言中已经涉及到字符串了,但是在 C 语言中要表示字符串只能使用字符数组或者字符指针,
可以使用标准库提 供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开
的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java 语言专门提供了 String 类
目录
[一、 常用方法](#一、 常用方法)
[1.1 构造方法](#1.1 构造方法)
[1.2 字符串比较](#1.2 字符串比较)
[1.2.1 == 比较是否引用同一个对象](#1.2.1 == 比较是否引用同一个对象)
[1.2.2 boolean equals(按照字典序比较 )](#1.2.2 boolean equals(按照字典序比较 ))
[1.2.3 int compareTo(String s) 方法: 按照字典序进行比较](#1.2.3 int compareTo(String s) 方法: 按照字典序进行比较)
[1.2.4 int compareToIgnoreCase(String str)](#1.2.4 int compareToIgnoreCase(String str))
[1.3 字符串查找](#1.3 字符串查找)
[1.4 转化](#1.4 转化)
[1.4.1 数值和字符串转化](#1.4.1 数值和字符串转化)
[1.4.2 大小写转换](#1.4.2 大小写转换)
[1.4.3 字符串转数组](#1.4.3 字符串转数组)
[1.4.4 格式化](#1.4.4 格式化)
[1.5 字符串替换](#1.5 字符串替换)
[1.6 字符串拆分](#1.6 字符串拆分)
[1.7 字符串截取](#1.7 字符串截取)
[1.8 其他操作方法](#1.8 其他操作方法)
[1.9 字符串的不可变性](#1.9 字符串的不可变性)
[2.1 StringBuilder的介绍](#2.1 StringBuilder的介绍)
一、 常用方法
1.1 构造方法
String类提供的构造方式非常多,常用的有以下三种
java
public static void main(String[] args) {
String s1 = "hello world!";
System.out.println(s1);
// 直接常量串构造
String s2 = new String("hellohellohello!");
System.out.println(s2);
//new一个
char[] arr = {'h', 'e', 'l', 'l', 'o'};
String s3 = new String(arr);
System.out.println(s3);
// 使用字符数组构造
}
需要注意的是String 是引用数据类型,内部并不存储字符串本身
在 Java 中 "" 引起来的也是 String 类型对象。
java
public static void main(String[] args) {
System.out.println("hello".length());
}
1.2 字符串比较
Java中提供了4种比较方式
1.2.1 == 比较是否引用同一个对象
因为 String属于引用数据类型,== 比较的是引用的地址
java
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);
}
1.2.2 boolean equals(按照字典序比较 )
String 类重写了父类 Object 中equals 方法,Object 中equals 默认按照 == 比较,String 重写
equals 方法
java
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2));
}
1.2.3 **int compareTo(String s)方法:**按照字典序进行比较
String 类中实现了Comparable 接口
实现了 compareTo方法
比较方法类似于C语言 中的strcmp
先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
如果前 k 个字符相等 (k 为两个字符长度最小值 ) ,返回值两个字符串长度差值
java
public static void main(String[] args) {
String s1 = new String("helloa");
String s2 = new String("hellob");
String s3 = new String("hello123456");
String s4 = new String("hello");
System.out.println(s1.compareTo(s2));
System.out.println("================");
System.out.println(s3.compareTo(s4));
}
1.2.4 int compareToIgnoreCase(String str)
与compareTo方式相同,但是忽略大小写比较
java
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("ABC");
String s3 = new String("ABc");
String s4 = new String("aBC");
System.out.println(s1.compareToIgnoreCase(s2));
System.out.println(s1.compareToIgnoreCase(s3));
System.out.println(s1.compareToIgnoreCase(s4));
}
1.3 字符串查找
String 类提供的常用查找的方法:
|--------------------------------------------|---------------------------------------------------------------|
| 方法 | 功能 |
| char charAt(int index) | 返回 index 位置上字符,如果 index 为负数或者越界,抛出 ndexOutOfBoundsException异常 |
| int indexOf(int ch) | 返回 ch 第一次出现的位置,没有返回 -1 |
| int indexOf(int ch, int fromIndex) | 从 fromIndex 位置开始找 ch 第一次出现的位置,没有返回 -1 |
| int indexOf(String str) | 返回 str 第一次出现的位置,没有返回 -1 |
| int indexOf(String str, int fromIndex) | 从 fromIndex 位置开始找 str 第一次出现的位置,没有返回 -1 |
| int lastIndexOf(int ch) | 从后往前找,返回 ch 第一次出现的位置,没有返回 -1 |
| int lastIndexOf(int ch, int fromIndex) | 从 fromIndex 位置开始找,从后往前找 ch 第一次出现的位置,没有返回-1 |
| int lastIndexOf(String str) | 从后往前找,返回 str 第一次出现的位置,没有返回 -1 |
| int lastIndexOf(String str, int fromIndex) | 从 fromIndex 位置开始找,从后往前找 str 第一次出现的位置,没有返回-1 |
注意:上述方法都是实例方法。
需要具体的对象去引用
1.4 转化
1.4.1 数值和字符串转化
数字转字符串可以使用 valueOf方法
可以看到valueOf是重载方法
java
public static void main(String[] args) {
String s1 = String.valueOf(123456);
System.out.println(s1);
String s2 = String.valueOf(521.2);
System.out.println(s2);
}
字符串转数字可以使用
Integer.parseInt
Double.parseDouble
等
java
public static void main(String[] args) {
String s1 = String.valueOf(123456);
System.out.println(s1);
String s2 = String.valueOf(521.2);
System.out.println(s2);
System.out.println("=============");
int data1 = Integer.parseInt(s1);
System.out.println(data1);
double data2 = Double.parseDouble(s2);
System.out.println(data2);
}
1.4.2 大小写转换
toUpperCase 转大写
toLowerCase 转小写
java
public static void main(String[] args) {
String s1 = "abcdefg";
String s2 = "ABCDEFG";
System.out.println(s1.toUpperCase());
System.out.println(s2.toLowerCase());
}
1.4.3 字符串转数组
可以使用 toCharArray方法
java
public static void main(String[] args) {
String s1 = "abcdefg";
char[] chars = s1.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
1.4.4 格式化
java
public static void main(String[] args) {
String s = String.format("%d-%d-%d", 1111, 1,11);
System.out.println(s);
}
1.5 字符串替换
使用一个指定的新的字符串替换掉已有的字符串数据
|-------------------------------------------------------|-----------|
| 方法 | 功能 |
| String replaceAll(String regex, String replacement) | 替换所有的指定内容 |
| String replaceFirst(String regex, String replacement) | 替换首个内容 |
java
public static void main(String[] args) {
String str = "hello" ;
System.out.println(str.replaceAll("l", "_"));
System.out.println(str.replaceFirst("l", "_"));
}
由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.
1.6 字符串拆分
|-------------------------------------------|------------------------|
| 方法 | 功能 |
| String[] split(String regex) | 将字符串全部拆分 |
| String[] split(String regex, int limit) | 将字符串以指定的格式,拆分为 limit 组 |
java
public static void main(String[] args) {
String str = "I love Java!";
String[] strings = str.split(" ");
for (String string:strings){
System.out.println(string);
}
}
java
public static void main(String[] args) {
String str = "I love Java!";
String[] strings = str.split(" ",2);
for (String string:strings){
System.out.println(string);
}
}
也会出现特殊情况
java
public static void main(String[] args) {
String str = "123.456.789";
String[] strings = str.split(".");
for (String string:strings){
System.out.println(string);
}
}
可以看到分割并没有成功
有些特殊字符作为分割符可能无法正确切分 , 需要加上转义
字符 "|" , "*", "+" 都得加上转义字符
对于split 这个方法来说 需要两个**\** 才能表示一个**\**
java
public static void main(String[] args) {
String str = "123.456.789";
String[] strings = str.split("\\.");
for (String string:strings){
System.out.println(string);
}
}
而如果是 "\\" ,那么就得写成 "\\\\"
java
public static void main(String[] args) {
String str = "123\\456\\789";
String[] strings = str.split("\\\\");
for (String string:strings){
System.out.println(string);
}
}
如果一个字符串中有多个分隔符,可以用"|"作为连字符.
java
public static void main(String[] args) {
String str = "name=12age%15&11";
String[] strings = str.split("=|%|&");
for (String string:strings){
System.out.println(string);
}
}
1.7 字符串截取
|------------------------------------------------|------------|
| 方法 | 功能 |
| String substring(int beginIndex) | 从指定索引截取到结尾 |
| String substring(int beginIndex, int endIndex) | 截取部分内容 |
java
public static void main(String[] args) {
String str = "hello world!";
System.out.println(str.substring(5));
System.out.println(str.substring(0,5));
}
需要注意的是他的区间是左闭右开
substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
1.8****其他操作方法
|---------------|----------------------|
| 方法 | 功能 |
| String trim() | 去掉字符串中的左右空格 , 保留中间空格 |
java
public static void main(String[] args) {
String str = " hello world! ";
System.out.println(str);
System.out.println(str.trim());
}
trim 会去掉字符串开头和结尾的空白字符 ( 空格 , 换行 , 制表符等 )
1.9 字符串的不可变性
String 是一种不可变对象 . 字符串中的内容是不可改变.
上述所有操作都是在操作完成后产生一个新的对象
而非在字符串上进行修改
java
public static void main(String[] args) {
String str = "hello world!";
System.out.println(str.toUpperCase());
System.out.println(str);
}
String 类中的字符实际保存在内部维护的 value 字符数组中
同时 value数组被 private 修饰 ,也没有提供 set方法
那就无法拿到 value 这个引用
就不能对其中的内容进行修改
String类被 final 修饰,表明该类不能被继承
value被修饰被 final 修饰,表明 value 自身的值不能改变,即不能引用其它字符数组,但是其引
用空间中的内容可以修改。
final 修饰类表明该类不想被继承, final 修饰引用类型表明该引用变量不能引用其他对象,但是其
引 用对象中的内 容是可以修改的 。
二、StringBuilder和StringBuffer
由于 String 的不可更改特性,为了方便字符串的修改,Java 中供 StringBuilder 和 StringBuffer
类。
java
public static void main(String[] args) {
String str = "hello";
str += "world!";
System.out.println(str);
}
这里看一下这部分代码的底层是怎么执行的
可以看到
底层在执行这段代码的时候其实进行了多部操作
其实这里相当于是这么写
java
public static void main(String[] args) {
String str = "hello";
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(str);
stringBuilder.append("world!");
str = stringBuilder.toString();
System.out.println(str);
}
这个过程中出现了 StringBuilder
java
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for(int i = 0; i < 10000; ++i){
s += i;
}
long end = System.currentTimeMillis();
System.out.println("String:" + (end - start));
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for(int i = 0; i < 10000; ++i){
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuffer:" + (end - start));
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for(int i = 0; i < 10000; ++i){
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuilder:" + (end - start));
}
这这一段代码中循环都是个字符串进行拼接
不同的是分别使用String StringBuffer StringBuilder
那么输出的是执行这一个过程需要的时间,单位是毫秒
可以看到
String 类的拼接效率远低于 StringBuffer StringBuilder
且 StringBuffer StringBuilder 之间的差距可以忽略不计
StringBuffer StringBuilder 拼接效率高的原因再与 append方法
再看一下这个代码的底层是怎么执行的
此处对应的是
这个循环
可以看到的是每次进入循环都需要new 一个对象
对应这个循环
可以看到的是他就不需要 new对象了
而 String 类型就是因为要不停的创建对象销毁对象
造成效率低下
因此:尽量避免对 String 的直接需要,如果要修改建议尽量
使用 StringBuffer 或者 StringBuilder 。
StringBuffer 的 append 是一个线程安全的方法
同一时间只有一个线程能够执行这个方法
为了保证这个线程安全
所以会有一些资源的消耗
就导致时间会比 StringBuilder 的 append时间长
2.1 StringBuilder****的介绍
StringBuilder 和 StringBuffer 类。这两个类大部分功能是相同的,这里介绍StringBuilder 常用
的一些方法,
|------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| 方法 | 功能 |
| StringBuff append(String str) | 在尾部追加,相当于 String 的 += ,可以追加: boolean 、 char 、 char[] 、 double、 float 、 int 、 long 、 Object 、 String 、 StringBuff 的变量 |
| char charAt(int index) | 获取 index 位置的字符 |
| int length() | 获取字符串的长度 |
| int capacity() | 获取底层保存字符串空间总的大小 |
| void ensureCapacity(int mininmumCapacity) | 扩容 |
| void setCharAt(int index, char ch) | 将 index 位置的字符设置为 ch |
| int indexOf(String str) | 返回 str 第一次出现的位置 |
| int indexOf(String str, int fromIndex) | 从 fromIndex 位置开始查找 str 第一次出现的位置 |
| int lastIndexOf(String str) | 返回最后一次出现 str 的位置 |
| int lastIndexOf(String str, int fromIndex) | 从 fromIndex 位置开始找 str 最后一次出现的位置 |
| StringBuff insert(int offset, String str) | 在 offset 位置插入:八种基类类型 & String 类型 & Object 类型数据 |
| StringBuffer deleteCharAt(int index) | 删除 index 位置字符 |
| StringBuffer delete(int start, int end) | 删除 [start, end) 区间内的字符 |
| StringBuffer replace(int start, int end, String str) | 将 [start, end) 位置的字符替换为 str |
| String substring(int start) | 从 start 开始一直到末尾的字符以 String 的方式返回 |
| String substring(int start, int end) | 将 [start, end) 范围内的字符以 String 的方式返回 |
| StringBuffer reverse() | 反转字符串 |
| String toString() | 将所有字符按照 String 的方式返回 |
String 、 StringBuffer 、 StringBuilder 的区别
String 的内容不可修改, StringBuffer 与 StringBuilder 的内容可以修改 .
StringBuffer 与 StringBuilder 大部分功能是相似的
StringBuffer 采用同步处理,属于线程安全操作;而 StringBuilder 未采用同步处理,属于线程不
安全操作