前言:String类是我们很常见的一种创建文本的类,但它也有许多有趣的地方,或者是可以深入了解一下的地方,所以我们本篇博客将带你深入String类。
上一篇博客中我们了解了字符串和字符,字节的比较,然后这一篇我们继续讲解到字符串中的奥秘。
每文一图:
深入String类一.字符串常见操作
1.字符串对比2.字符串查找
1.public boolean contains(CharSequence s)2.public int indexOf(String str)3.public int lastIndexOf(String str)4.public boolean startsWith(String prefix)5.public boolean endsWith(String suffix) 3.字符串替换4.字符串拆分5.字符串截取
一.字符串常见操作我们在对比完字符字节还有字符串之后,就到了比较字符串和字符串啦,所以接下来就是字符串的常见操作了:比较查找拆分替换等等。
1.字符串对比在之前,我们使用过String类提供的equals()方法,该方法本身是可以进行区分大小写的相等判断。我们可以来看一下:
public static void main(String[] args) {
String str = "hello";
String str2 = "world";
System.out.println(str.equals(str2));
//打印false
}
这里就是我们对于equals的使用方法,将两个字符串进行比较,一样返回true,不一样就false。我们可以看看他的底层源码(在IDEA中按住ctrl然后左键点击equals):
public boolean equals(Object anObject) {
//判断是否是相同
if (this == anObject) {
return true;//判断两者的地址是不是一样
//也就是比较两者的引用指向的地方
}
if (anObject instanceof String) {
//判断两者类型是否一样,比如说一个数组一个字符串,就不会进入循环
String anotherString = (String)anObject;
//把这个元素变成字符串
int n = value.length;//计算长度
if (n == anotherString.value.length) {
//长度不一样就进不去
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])//进去了之后就一一下标对比
return false;
i++;
}
return true;
}
}
return false;
}
这就是equals方法的基本原理。这其实也是我们字符串对比方法中的其中一种,关于对比字符串的方法,我们也列出了一个表格:
| NO | 方法名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | public boolean equals(Object anObject) | 普通 | 区分大小写的比较 |
| 2 | public boolean equalsIanoreCase(String anotherString) | 普通 | 不区分大小写的比较 |
| 3 | public int compareTo(String anotherString) | 普通 | 比较两个字符串大小关系 |
然后就到我们的第二个比较方法equalsIanoreCase,这里我们在表格中就知道了,和上面的equals不一样的是,对于这个方法就是不会区分字符串中的大小写对比,我们来看一下吧:
public static void main(String[] args) {
String str = "hello";
String str2 = "Hello";
System.out.println(str.equals(str2));
//打印false
//equals区分大小写,所以输出false
}
public static void main(String[] args) {
String str = "hello";
String str2 = "Hello";
System.out.println(str.equalsIgnoreCase(str2));
//打印true
//加上了IgnoreCase意为忽略一些东西,不计较大小写,所以输出true
}
这就是equalsIgnoreCase的使用方法。
然后就到了我们第三个方法compareTo了,对于前面两个方法,其实都是比较真假,也就是对比两个字符串,一样返回真,不一样返回假。而这个方法就是比较大小,我们来看看:
我们先写一个这样的代码运行:
public static void main(String[] args) {
String str = "abc";
String str2 = "Abc";
System.out.println(str.compareTo(str2));
//打印32
}
那么接下来就是解析一下:
其实,对于compareTo来说,实际上是对比的是字符的值或者长度,我们先来看一下他的源码:
public int compareTo(String anotherString) {
//比较长度
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
//比较字符的长度
}
k++;
}
return len1 - len2;
}
对于compareTo这个方法,它的使用是这样子的:
1.返回参与比较的前后两个字符串的ascii码的差值,如果两个字符串首字母不同,则该方法返回首字母的ascii码的差值。
比如这里就是对比了a和A:
public static void main(String[] args) {
String str = "abc";
String str2 = "Abc";
System.out.println(str.compareTo(str2));
//a和A相差的ascii码是32
}
2.即参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的ascii码差值。
比如这里就是比较c和C的ascii码:
public static void main(String[] args) {
String str = "abC";
String str2 = "abc";
System.out.println(str.compareTo(str2));
//C和c相差的ascii码是-32
}
3.如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值。
比如说下面的两个字符串就不一样长:
public static void main(String[] args) {
String str = "abcdef";
String str2 = "abc";
System.out.println(str.compareTo(str2));
//打印 3 因为str比str2长了三个字符
}
而这几个规则都有一个特点:
返回为正数表示str>str2, 返回为负数表示str
这里比较几个案例来整合一下这个方法的规则:
public static void main(String[] args) {
String str1 = "abcde";
String str2 = "abcdE";
String str3 = "abc";
String str4 = "bcde";
String str5 = "AbcdE";
System.out.println(str1.compareTo(str2));//对比前面的都一样,到e和E对比相差32
System.out.println(str1.compareTo(str3));//前面的字符相同,长度不同,输出长度2
System.out.println(str1.compareTo(str4));//第一个字符是a和b,对比差-1,不需要看长度
System.out.println(str1.compareTo(str5));//第一个字符是a和A,对比差32,不需要看后面的字符
}
总结:字符串比较大小的时候,先从头开始一个一个对比,有不同的就返回相差的ascii码值,如果前面的都相同,且字符串长度一样,则返回0,如果长度不相同,就返回字符串长度之差。
附图ascii表:
2.字符串查找
对于查找字符串,这里同样有着很多方法(见下表),接下来我们挨个进行了解。
| NO | 方法名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | public boolean contains(CharSequence s) | 普通 | 判断一个子字符串是否存在 |
| 2 | public int indexOf(String str) | 普通 | 从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1 |
| 3 | public int indexOf(String str,int fromIndex ) | 普通 | 从指定位置开始查找子字符串位置 |
| 4 | public int lastIndexOf(String str) | 普通 | 由后向前查找子字符串位置 |
| 5 | public int lastIndexOf(String str,int fromIndex) | 普通 | 从指定位置由后向前查找 |
| 6 | public boolean startsWith(String prefix) | 普通 | 判断是否以指定字符串开头 |
| 7 | public boolean startsWith(String prefix,int toffset) | 普通 | 从指定位置开始判断是否以指定字符串开头 |
| 8 | public boolean endsWith(String suffix) | 普通 | 判断是否以指定字符串结尾 |
1.public boolean contains(CharSequence s)
对于contains这个方法来说,就是在其源字符串中寻找是否存在目标字符串的一个判断方法,也就是判断一个子字符串是否存在,比如下面这个例子:
public static void main(String[] args) {
String str = "ababcabcd";//源字符串str
String tmp = "abc";//目标字符串tmp
boolean flg = str.contains(tmp);//格式
System.out.println(flg);
//如果有则输出true 反之false
}
2.public int indexOf(String str)
对于indexOf方法我们可以看到其返回值是int类型,实际上他的作用就是从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1,注意:这里的查到是查到的第一个位置,后面有重复的字符串也是会返回第一个查到的位置。
public static void main(String[] args) {
String string = "ababcabcd";
String str = "abc";
int index = string.indexOf(str);//类似于c中的strstr -> KMP算法
System.out.println(index);
//返回2
}
然后我们看表格中的第三个就是多了一个参数int fromIndex,这里就是在上面这个方法的前提下,指定了开始位置,从指定位置开始查找子字符串位置。比如:
public static void main(String[] args) {
String string = "ababcabcd";
String str = "abc";
int index = string.indexOf(str,2);//如果是2,从abcabcd开始找
System.out.println(index);//返回2
}
public static void main(String[] args) {
String string = "ababcabcd";
String str = "abc";
int index = string.indexOf(str,3);//如果是3,从bcabcd开始找
System.out.println(index);//返回5
}
3.public int lastIndexOf(String str)
lastIndexOf顾名思义,叫做从后往前找,和前面的从前往后找是异曲同工的,我们来看个例子就理解了。
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.lastIndexOf(tmp));
//从后往前数,找到tmp的字符串,返回5
}
找到的是str中的从后面开始看见的第一个abc,所以返回的值是5。
同样的,上面的从前往后走有选择位置,我们从后往前数怎么能没有呢,所以我们也有int fromIndex,可以是选择从指定位置开始从后往前数,比如:
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.lastIndexOf(tmp,6));
//这里也就是从ababcab最后一个b开始往前找,同样的是找到前一个的a的时候
//所以返回值还是5
}
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.lastIndexOf(tmp,4));
//变成4之后是从ababc的c开始往前找
//所以返回值是2
}
4.public boolean startsWith(String prefix)
从表格中的说明我们可以看出这个方法的作用是判断是否以指定字符串开头,也就是我们在参数中输入一个字符串,判断是否是以这个字符串开头,是返回true,否则返回false,比如:
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.startsWith("a"));
System.out.println("==================");
System.out.println(str.startsWith("ac"));
//输出 true
// ==================
// false
}
同样的这里也有偏移量之后确定开始位置,也就是增加一个参数是int toffset,变成从指定位置开始判断是否以指定字符串开头,比如:
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.startsWith("c",4));
//从ababc的c开始,所以判断是否是c开头,返回值为true
}
5.public boolean endsWith(String suffix)
有判断开头的方法,就可以有判断结尾的方法,这里的endsWith就是判断是否以指定字符串结尾,比如:
public static void main(String[] args) {
String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.endsWith("cd"));
//以cd结尾的,所以返回值是true
}
3.字符串替换
使用一个指定的新的字符串替换掉已有的字符串数据,也就是字符串替换,有一个方法叫replace,也就是代替的意思,当我们在IDEA中输入replace的时候,会出现这几个方法:
我们来看一下:
其实第一个的参数中就说明了,它是char类型,所以是一个字符,那么它的意思就是把字符串中这个旧字符替换为新字符:
public static void main(String[] args) {
String str = "ababcabcdabcde";
str.replace('a','g');
System.out.println(str);
//返回ababcabcdabcde
}
咦?这里不是说替换了吗,为什么返回的是一样的呢,其实我们点开replace的源代码,我们可以看见它实际上在替换的过程中,是new String的,所以对于上面的代码,输出的并不是我们替换后的字符串。
正确的我们应该接收返回值,再输出:
public static void main(String[] args) {
String str = "ababcabcdabcde";
String ret = str.replace('a','g');
System.out.println(ret);
//返回gbgbcgbcdgbcde
}
然后对于后面的三个replace就是对字符串的替换了,第二第三个就是将全部的旧字符串换成新的字符串,第四个就是只将第一个旧字符串替换成新字符串。下面是例子:
public static void main(String[] args) {
String str = "ababcabcdabcde";
String ret = str.replace('a','g');
System.out.println(ret); //返回gbgbcgbcdgbcde
//将字符a都换成字符g
System.out.println("====================");
String ret2 = str.replace("ab","hh");
System.out.println(ret2);//返回hhhhchhcdhhcde
//将字符串ab都换成字符串hh
System.out.println("====================");
String ret3 = str.replaceAll("ab","gg");
System.out.println(ret3);//返回ggggcggcdggcde
//将字符串ab都换成字符串gg
System.out.println("====================");
String ret4 = str.replaceFirst("ab","gg");
//只将第一个字符串ab换成字符串gg
System.out.println(ret4);//返回ggabcabcdabcde
}
4.字符串拆分
| No. | 方法名称 | 类型 | 描述 |
|---|---|---|---|
| 1. | public String[] split(String regex) | 普通 | 将字符串拆分 |
| 2. | public String[] split(String regex,int limit) | 普通 | 将字符串部分拆分,该数组长度就是limit极限 |
字符串拆分是用到一个split的方法,这里的话我们可以直接举例子,大家在看例子的时候就会明白split是什么了:
public static void main(String[] args) {
String str = "name=zhangsan&age=19";//原字符串
String[] strings = str.split("&");//注意:返回值是带[]的数组
//以"&"作为拆分符号 拆分结果用strings接收
for(String s:strings){
//接收strings内容
System.out.println(s);
//打印s
}
//结果为:name=zhangsan
// age=19
}
这就是split的使用,但是在拆分字符串的时候我们还有要注意的地方,比如下面几个例子:
1.特殊字符
public static void main(String[] args) {
String str = "192.168.1.1";
String[] strings = str.split(".");
for (String s:strings) {
System.out.println(s);
//按照常理来说,这里应该打印192 168 1 1
//但是这里并没有打印
}
}
这里因为 . 是一个特殊字符,如果我们需要以它为拆分字符的时候,要在前面添加转义字符 ,然后因为转义字符 也是特殊字符,所以这里应该写为"\.",所以正确的代码应该是:
public static void main(String[] args) {
String str = "192.168.1.1";
String[] strings = str.split("\.");
for (String s:strings) {
System.out.println(s);
//打印192 168 1 1(隔行打印的)
}
}
注意:1. 字符"|","*","+"都得加上转义字符,前面加上""。
然后我们在上面的时候还有另一个分割的方法,其实就是多了一个 limit 参数,这个参数的意思就是拆分最多拆多少组,比如:
public static void main(String[] args) {
String str = "192.168.1.1";
String[] strings = str.split("\.",2);
//这里就是最多拆分为两组 所以分割一次之后就不分后面的了
for (String s:strings) {
System.out.println(s);
}
//打印192 168.1.1(隔行打印)
}
注意: 2.而如果是"",那么就得写成"\".
那么我们如果想分割更细呢,也就是说我们想要有多个分割符,该怎么办呢,这里我们有一个分割符的连接符"|",例如:
public static void main(String[] args) {
String str = "zhangsan&hhh#123";
String[] strings = str.split("&|#");//&和#都是分割符
for (String s:strings) {
System.out.println(s);
}
//打印的是zhangsan hhh 123
}
注意: 3. 如果一个字符串中有多个分隔符,可以用"|"作为连接字符。
5.字符串截取
从一个完整的字符串之中截取出部分内容。如下表:
| No. | 方法名称 | 类型 | 描述 |
|---|---|---|---|
| 1. | public String substring(int beginIndex) | 普通 | 从指定索引截取到结尾 |
| 2. | public String substring(int beginIndex,int endIndex) | 普通 | 截取部分内容 |
然后就到我们的截取字符串了,在我们的截取方法中有一个参数的,有两个参数的,这里的参数其实就是截取部分的起点或终点。
比如:
public static void main(String[] args) {
String str = "zhangsan&hhh#123";
String sub = str.substring(2);//从下标为2的地方开始截取到结尾
System.out.println(sub);
//打印angsan&hhh#123
}
这里同样的是创建了新的字符串,然后如果是str.substring(0)的话,就是输出原来的字符串,并不会创建新的字符串。然后第二种就是我们的头尾都控制的截取:
public static void main(String[] args) {
String str = "zhangsan&hhh#123";
String sub = str.substring(2,5);
//从下标2开始截取字符串到5下标(java中一遍是左闭右开,没有5下标的内容)
System.out.println(sub);
//打印ang
}
这就是本篇深入String类3的全部内容啦,接下来我们还有深入String类4,里面会讲解到其他字符串的方法,以及StringBuffer 和 StringBuilder两个大考点。欢迎关注。一起学习,共同努力!也可以期待这个系列接下来的博客噢。
链接:都在这里! Java SE 带你从零到一系列
还有一件事:



