深入理解Java中的子字符串操作
本文旨在帮助大家深入理解 Java 中子字符串的概念及其应用。除了理论知识,我们还会通过具体的代码示例来辅助理解,教你如何创建子字符串,并在字符串中查找子字符串,让抽象的概念变得生动形象。
在深入学习之前,我们首先要了解子字符串的基础知识。
什么是字符串和子字符串?
在Java中,字符串被定义为一系列字符的序列。每一个字符串都是一个对象。Java中的字符串可以包含各种字符,例如字母、数字、符号甚至是空格。而子字符串则是指包含在一个较大字符串中的一部分字符序列,它是字符串的子集。
例如,“Geek”可以看作是字符串“techblik.com”的一个子字符串。使用子字符串,我们可以提取字符串中的特定片段。
例如,假设你有一个名字“John Doe”,如果你只想提取“John”,就可以使用子字符串轻松实现。 此外,如果你有一个名字列表“John, Jack, Jolly”,并且想确认“John”是否在其中,子字符串也能派上用场。 以上只是子字符串的一些应用场景,一旦你掌握了它,就能在各种操作中灵活运用。
现在,我们已经对Java中子字符串的概念有了一定的了解。接下来,让我们看看如何在Java中创建和使用它们。
#1. 利用`substring()`方法
`substring()`方法是创建子字符串的利器。它接受一个或两个参数作为输入,分别是起始索引 `startIndex` 以及可选的结束索引 `endIndex`,最终返回我们所需要的子字符串。
根据参数的个数,`substring()`方法有两种使用方式。下面让我们详细了解一下。
`substring(int startIndex)`
第一种形式是 `substring(startIndex)`。该方法接受一个整数值作为参数,这个整数代表子字符串的起始位置。它返回从给定的起始索引开始直到原始字符串末尾的子字符串。
下面是一个代码示例:
public class Substrings{ public static void main(String args[]){ String str="techblik.com"; System.out.println("原始字符串: " + str); System.out.println("子字符串: " +str.substring(4)); //字符串索引从0开始 } }
输出结果如下:
原始字符串: techblik.com 子字符串: blik.com
从输出结果可以看出,原始字符串是“techblik.com”,而返回的子字符串是“blik.com”。它从索引为4的位置(即第5个字符)开始,截取到字符串的末尾。
`substring(int startIndex, int endIndex)`
这是使用 `String` 类的 `substring` 方法的另一种方式。我们可以向 `substring` 方法传递两个整数:起始索引和结束索引。它的格式为`substring(startIndex, endIndex)`。
为了更深入地理解,我们来看一些代码示例:
public class Substrings{ public static void main(String args[]){ String str="GeekFlareFans"; System.out.println("原始字符串: " + str); System.out.println("子字符串: " +str.substring(4,9)); //获取索引为4到8的子字符串 } }
输出结果为:
原始字符串: GeekFlareFans 子字符串: Flare
如你所见,给定字符串“GeekFlareFans”,输出的子字符串为“Flare”。我们传递的起始索引为4,结束索引为9。它从索引为4的元素开始,到索引为9之前结束。需要注意的是,它不包括结束索引对应的元素。它返回的子字符串包含了结束索引之前的所有元素,但不包含结束索引处的元素。
#2. 利用`split()`方法
`split()`方法是Java中`String`类的另一个非常有用的方法,它可以帮助我们创建子字符串。当我们需要处理包含用公共分隔符分隔的多条信息的字符串时,这个方法非常实用。
语法中提到了“正则表达式”这个术语,这可能会让你感到有些困惑,所以我们先来了解一下正则表达式。正则表达式是“Regular Expression”的缩写,它是一系列用于描述字符串或文本模式的字符序列。在`split`方法的上下文中,正则表达式就是我们的分隔符。
`split()`方法最多接受两个参数作为输入,分别是正则表达式字符串和限制整数。正则表达式是分隔符,当找到分隔符时,原始字符串会被分割成两部分:分隔符之前的部分和分隔符之后的部分。
例如,假设我们要用正则表达式“bcd”来分割字符串“abcdef”,那么我们会得到两个子字符串“a”和“ef”。
该方法返回一个包含分割后字符串的数组。我们可以只指定正则表达式,也可以同时指定正则表达式和限制。下面我们分别了解该方法的各种调用方式。
`split(String regex)`
第一种方法仅接收一个正则表达式字符串,格式为`split(regex)`。它没有限制参数,因此返回数组中所有分隔的子字符串。
让我们通过一些代码来更清晰地理解:
public class Substrings{ public static void main(String args[]){ String str="Geek%Flare"; String[] substrings=str.split("%"); System.out.println("原始字符串: " + str); System.out.println("第一个子字符串: " + substrings[0]); System.out.println("第二个子字符串: " + substrings[1]); } }
输出结果如下:
原始字符串: Geek%Flare 第一个子字符串: Geek 第二个子字符串: Flare
正如我们从代码中看到的那样,给定的字符串包含一个分隔符正则表达式“%”。分隔符不一定是单个字符,它可以是包含任意数量字符的任何字符串。 `split()`方法会忽略这个正则表达式,并返回所有由这个正则表达式分隔的子字符串。这些子字符串会被存储在数组中。
在示例代码中,给定的字符串是“Geek%Flare”。因此,我们得到了一个包含两个元素的数组,分别是“Geek”和“Flare”。然后我们通过它们的索引(分别为0,1)访问它们,并将“Geek”和“Flare”打印到控制台。
这里我们还需要注意,如果方法没有传递任何参数,将会抛出一个错误。但是,如果我们传递一个空字符串(””)作为正则表达式,那么我们会得到每一个单独的字符作为子字符串。让我们通过示例来验证。
import java.util.Arrays; public class Substrings{ public static void main(String args[]){ String str="Geek%Flare"; String[] substrings=str.split(""); System.out.println(Arrays.toString(substrings)); } }
输出结果为:
[G, e, e, k, %, F, l, a, r, e]
如示例所示,当正则表达式参数为空字符串时,它会返回所有字符作为单独的子字符串,我们可以通过打印`split()`方法输出的数组清楚地看到这一点。
`split(String regex, int limit)`
使用该方法的第二种变体,我们可以更好地控制输出,并且可以进一步微调`split()`方法的输出。在这种情况下,`split()`方法接受两个参数作为输入。除了正则表达式,我们还会以`split(regex, limit)`的格式给出一个限制参数。
这里的`limit`指的是输出结果字符串的数量。根据`limit`值的不同,存在三种可能性:
情况 1: 如果 `limit > 0`,则结果数组将包含输出,但分割操作最多会执行 `limit-1` 次。在这种情况下,结果数组包含的元素不会超过指定的限制,并且所有未分割的剩余字符串会原样存储。让我们用代码来更好地理解。
import java.util.Arrays; public class Substrings{ public static void main(String args[]){ String str="Geek%Flare%is%the%best"; String[] substrings=str.split("%",2); System.out.println(Arrays.toString(substrings)); } }
输出结果为:
[Geek, Flare%is%the%best]
查看输出结果,我们发现数组中只有两个元素,也就是 `limit` 参数中指定的数字。另外需要注意的是,分割操作只执行了一次,即 `limit – 1`次。
然而,如果正则表达式连续出现两次(”%%”),那么将会产生一个空的子字符串。下面的代码可以帮助你更好地理解:
import java.util.Arrays; public class Substrings{ public static void main(String args[]){ String str="Geek%Flare%is%%the%best%%%"; String[] substrings=str.split("%",5); System.out.println(Arrays.toString(substrings)); } }
输出结果如下:
[Geek, Flare, is, , the%best%%%]
基本上,如果 “%” 后面跟着另一个 “%” 或者字符串的结尾,它就会被转换成一个空子字符串。
情况 2: 如果 `limit < 0`,分割操作将会执行尽可能多的次数,对数组大小没有任何限制,但如果正则表达式连续出现两次(“%%”),则数组中会包含空子字符串。
import java.util.Arrays; public class Substrings{ public static void main(String args[]){ String str="Geek%Flare%is%%the%best%%%"; String[] substrings=str.split("%",-1); System.out.println(Arrays.toString(substrings)); } }
输出结果为:
[Geek, Flare, is, , the, best, , , ]
从输出中可以看到,分割操作执行了尽可能多的次数,并且还存在空子字符串。
情况 3: 如果 `limit = 0`,分割操作也会执行尽可能多的次数,但这里字符串末尾的所有空子字符串都将从数组中被丢弃。
import java.util.Arrays; public class Substrings{ public static void main(String args[]){ String str="Geek%Flare%is%%the%best%%%"; String[] substrings=str.split("%",0); System.out.println(Arrays.toString(substrings)); } }
输出结果如下:
[Geek, Flare, is, , the, best]
我们可以看到,当 `limit = -1` 和 `limit = 0` 时,输出结果非常相似,但是缺少了末尾的空子字符串。换句话说,子字符串数组末尾的空子字符串被忽略了。
另外需要注意的是,如果字符串中不存在正则表达式,它将返回整个原始字符串作为结果。
查找字符串是否包含子字符串
除了从现有字符串创建子字符串外,我们还可以判断一个字符串是否包含特定的子字符串。这在很多场景下都非常有用。那么,如何实现呢?有很多方法可以帮助我们实现这一目标。让我们逐一分析。
利用`contains()`方法
我们可以使用`contains()`方法轻松确定子字符串是否存在。 `String` 类的这个方法接受一个字符串作为输入,也就是我们需要查找的子字符串,并返回一个布尔值,表示子字符串是否在原始字符串中。此方法可以在 `if-else` 块、三元运算符和其他各种场景中使用来实现复杂的逻辑。
让我们更深入地了解一下这个方法。
public class Substrings{ public static void main(String args[]){ String str="techblik.com"; System.out.println("是否包含 Flare? \n"+ str.contains("blik")); } }
输出结果为:
是否包含 Flare? true
这段代码检查字符串“techblik.com”中是否包含“blik”,成功找到后,它返回一个布尔值“true”,从而确认了子字符串的存在。
public class Substrings{ public static void main(String args[]){ String str="techblik.com"; System.out.println("是否包含 Flare? \n"+ str.contains("Flare1")); } }
输出结果为:
是否包含 Flare? false
从示例中我们了解到,如果子字符串不在原始字符串中,该方法将返回 `false` 以表示其不存在。这样我们就可以很容易地确定子字符串是否存在。
查找子串的位置
#1. 利用`indexOf()`方法
`indexOf()`方法可以用来查找子字符串是否存在,并返回其索引位置。该方法接收一个字符串或字符作为输入,并给出其第一次出现的位置。但是它只能返回第一次出现的索引,并不能确认是否还有其他出现的情况。另一个需要注意的是,如果子字符串不存在,该方法会返回`-1`。
下面让我们进一步探讨一下这个方法。
public class Substrings{ public static void main(String args[]){ String str="GeekFlareGeekFlare"; System.out.println("Flare的索引: "+ str.indexOf("Flare")); } }
输出结果为:
Flare的索引: 4
在示例中,子字符串“Flare”第一次出现在字符串“GeekFlareGeekFlare”的索引为4的位置。因此,该函数按照预期返回了索引。
#2. 利用`lastIndexOf()`方法
`lastIndexOf()`方法与`indexOf()`方法非常相似。这两种方法都接受子字符串作为输入,并返回其位置的索引。当在指定的字符串中找不到子字符串时,它们的返回值也是相同的,都会返回`-1`。
但是,`indexOf()`方法返回子字符串第一次出现的索引,而`lastIndexOf()`方法返回子字符串最后一次出现的位置。
让我们通过代码看看它的实际效果:
public class Substrings{ public static void main(String args[]){ String str="GeekFlareGeekFlare"; System.out.println("Flare最后一次出现的索引: "+ str.lastIndexOf("Flare")); } }
输出结果为:
Flare最后一次出现的索引: 13
观察输出结果,我们了解到`lastIndexOf()`方法按照预期执行,并且我们获取了子字符串“Flare”在字符串“GeekFlareGeekFlare”中最后一次出现的索引。
常见问题解答
如何使用`split()`方法创建非空的子字符串?
如果主字符串中存在多个正则表达式字符串的实例(例如,“Hello%%Hi”,正则表达式为“%”),`split()`方法会将第一个实例作为分隔符,而其余的实例会输出空字符串。为了解决这个问题,我们可以将限制参数指定为 0。这样它只会给出非空的字符串作为输出。
`indexOf()`方法是否返回子字符串所有实例的索引?
否,`indexOf()`方法不会返回子字符串所有实例的索引。使用`indexOf()`,我们会得到一个整数返回值,其中包含了子字符串第一次出现的索引。但如果找不到子字符串,该方法会返回-1。
如果字符串中不存在给定的索引,`substring()`方法会返回什么?
如果字符串中不存在给定的起始索引和结束索引,编译器会抛出一个错误,也就是 “java.lang.StringIndexOutOfBoundsException:”,并且程序根本不会执行。
结论
在本文中,我们讨论了关于如何使用子字符串的各种方法和关键要点。我们探讨了如何创建子字符串,以及如何检查字符串中是否存在特定的子字符串。这将帮助你更好地理解如何使用子字符串。请多加练习,以全面掌握子字符串的运用。
接下来,你可以查看我们的 Java面试问题列表。