字符串这个词我想同学们并不陌生,但Java语言中的字符串和我们之前所学习的C语言字符串,差别可谓是非常之大,因为在C语言当中,想要表示一个字符串,就只能使用字符数组或字符指针,但是这种" 对数据进行细致的操作 " 和 " 将操作数据与方法分开 "的方式,并不符合我们Java的" 面向对象思想 ",于是Java语言提供了专门的String类:
一、String的常用方法
① 字符串构造
📚 关于字符串的构造,常用的有以下三种:
1. 使用常量字符串构造
2. new String对象
3. 使用字符数组进行构造
📖 虽然构造方式众多,但同样也是有区别的:
4. 构造方式的区别
📕 当我们使用第一种方法:"使用常量字符串构造" 时,我们创建出来的字符串是在"常量池"中的,而当我们创建出第一个字符串后,再创建内容相同的第二个字符串时,就会从之前在"常量池"中查找之前使用过的"常量字符串",如果能查找到,就会直接使用这个常量字符串,并且不会再创建新的常量字符串,找不到则反之。
📌 图示:
由此我们可以知道,s1和s2其实本质上是一样的:
📕 当我们使用第二种方法:" new String对象 "创建字符串时,创建的就是两个不同的字符串了~
使用new关键字构造出的字符串,不再是去"常量池"中寻找"常量字符串",而是在"堆内存"中存储,并且“每一次构造都会申请一个内存空间”,所以当我们使用 new 创建两个"Hello World"时,代表两个字符串内容相同,但地址并不相同。
📌 图示:
由此我们可以知道,s1和s2其实本质上是不同的:
② 字符串的比较
📖 其实我们刚刚已经稍微了解到了字符串的比较,那么接下来让我们细致的讲解:
1. " == "比较
用" == "比较字符串,比较直白地描述其实就是:比较两个字符串的"地址"是否相同。
" s == s0 "得到的是"true"是因为两者都是使用"常量池中的同一个位置的同一个字符串",故两者地址是相同的。
" s == s1 "得到的是"false"是因为s指代的是"常量池中的字符串",而s1指代的是"堆内存中的字符串",故两者地址不同。
" s1 == s2 "得到的是"false"是因为使用new创建字符串时,"每一次构造都会申请一个内存空间",故两者地址不同。
" s1 == s3 "得到的是"true"是因为s3 = s1时将地址也传了过去,于是两者地址相同。
2. "equals()"方法比较
用"equals()"方法比较字符串其实就是:对字符串中的内容进行比较
虽然这几个字符串的构造方式并不相同,但它们的内容都是相同的,所以当我们使用equals()进行比较时,显示出的反馈都是true~
但当我们使用equals()方法去比较自定义类型"People"时,即使他们的内容相同,我们得到的反馈却是false,这是为什么呢?
这是因为在编译器中,我们的equals()方法并没有自动配置出比较自定义类型的功能,如果我们想要使用equals()方法去比较自定义类型,就必须自己去对方法进行重写:
而我们全能的idea~已经帮我们自动配置好了"快捷重写equals()"的功能:
而当我们进入String里头去,就会发现:
我们的编译器已经自动写好了String的equals()方法~
3. compareTo()方法比较
compareTo()方法同样能比较两个字符串,而与equals()方法有所不同的是,compareTo()方法比较能够返回的类型是int,而非boolean,这同时也就代表着compareTo()方法是能够返回"正数,负数"的,也就代表着compareTo()方法在一些情况下能够比较两个字符串的大小关系~
我们可以看到,这时就能够通过返回值的大小,对字符串的大小进行比较了~
compareTo()方法的比较规则:
📕 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
📕 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
4. compareTolgnoreCase()比较
此方法与"compareTo"方法大同小异,唯一的区别只是,使用"compareTolgnoreCase"方法比较字符串时,会省略字母的大小写~
③ 字符串查找
1. charAt(int index)查找
📕 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常
(返回的是索引,第一个字符是从0算起而非1)
2. indexOf()查找
📕 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 lastIndex(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;
📖 我们可以使用刚刚学习到的这几个查找方法,尝试去做一个小练习:
练习:字符串中的第一个唯一字符
给定一个字符串 s ,找到它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。
示例:
输入: s = "leetcode" 输出: 0 输入: s = "loveleetcode" 输出: 2 输入: s = "aabb" 输出: -1
思路:我知道大家有思路,但是既然说是使用"字符的查找"来解题,那我们就不用大家心中的"创建数组,遍历字符串,出现字符对应数组下标+1"的这种做法啦~
我们首先想一下:应该如何判断字符是否为字符串中的单一字符?
单一字符肯定只会出现一次吧?而我们上面有两个方法:
📕 int indexOf(int ch):返回ch第一次出现的位置
📕 int lastIndex(int ch):从后往前找,返回ch第一次出现的位置
而如果是单一字符,我们使用这两种方法进行查找,得到的位置肯定相同,而如果不是单一字符,第一次出现肯定小于第二次出现~
而题中说的是"字符串第一个单一字符",我们就可以通过遍历字符串,进行查找:
但是我们可以看到,此时这个代码所消耗的时间并不是很优,只超过了50%的人;如此我们可以进行一下改进:(遍历字符串过程中,如果有出现已出现过的字符,我们便跳过该字符)
如此,效率便大大提高啦~
④ 字符串的转化
1. 字符串与数值的转化
📕 其他类型转换成字符串:
📕 字符串转换成其他类型:
2. 大小写转换
📕 toUpperCase():将小写字符转换成大写字符;
(注意:String是不可修改的类型,所以使用这些转换操作时,都不是对本字符串进行的操作,而是创建出一个新字符串,并且需要使用一个字符串来接收)
📕 toLowerCase():将大写字符转换成小写字符;
3. 字符串转数组
📕 toCharArray():将字符串转换成由多个字符组成的char[]数组;
⑤ 字符串替换
1. replace
📕 将字符串中某个字符替换成新的字符:
2. replaceFirst
📕 将字符串中某个字符串第一次出现的位置替换成新字符串:
3. replaceAll
(这个方法非常重要,并且很多时候都能用得上,因为它不仅可以接收单一的字符或者字符串,它还可以接收[正则表达式]~)
📕 去除字符串中除了[a-zA-Z_0-9]以外的所有字符:
📕 去除字符串中除了[0-9]以外的所有字符:
📕 可以按照自己想要的模式进行替换:
比如:把 hello world 中的 ' l ',' e ',' o '都替换成0:
还有很多种不同的搭配,大家可以在学习了正则表达式之后自行测试~
⑥ 字符串拆分
📕 split(String regex):将字符串全部拆分
📕 split(String regex, int limit):将字符串拆分成limit组
⑦ 字符串截取
📕 substring(int beginIndex):从指定索引截取到结尾
📕 substring(int beginIndex, int endIndex):截取部分内容
我们再额外学习一个实用的小方法:
📕 trim():去掉字符串中的左右空格,保留中间空格
我们使用这个方法,结合以上的方法来尝试做一个小练习:
练习:最后一个单词的长度
📖 给你一个字符串
s
,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。单词 是指仅由字母组成、不包含任何空格字符的最大子字符串
想好了嘛?这题!其实我们只需要用一行!就能做出来~你敢信嘛?
其实很简单,首先使用trim()方法去除字符串两边的空格,然后使用split(" ")将字符串通过空格分隔开,最后获取该字符串数组的最后一位,取其长度返回就好啦~
二、StringBuilder和StringBuffer
因为String的字符串是无法进行修改的,因此在Java中也为我们适配了对应可以进行修改的字符串
① append方法
📕 append方法用于将一个字符串追加到现有的 StringBuilder 对象末尾:
② insert方法
📕 insert方法用于在指定位置插入字符串:
③ delete方法
📕 delete方法用于删除字符串中指定范围的子串:
④ reverse方法
📕 reverse方法用于反转字符串:
⑤ setLength方法
📕 用于设置字符串的长度,可能截断或补零:
练习:验证回文串
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
📖 思路:
📕 先使用"toLowerCase()方法"将字符串全部变成小写字符
📕 然后使用"replaceAll()方法"将不是小写字符和不是数字的字符都删除
📕 然后我们创建一个"StringBuilder"对象来接收当前的s字符串
📕 我们对刚创建出的StringBuilder对象进行"reverse()"反转,然后再变成String型
📕 最后使用"equals()"方法判断反转后的字符串与反转前的字符串内容是否相等
📚 代码实现:
(纯为了提高字符串方法使用的熟练度,补药在意用时...)
那么关于String类的相关知识,就为大家分享到这里啦,如果有什么讲的不清楚,或者不够准确的地方还请大家多多指出,我也会虚心改正的,那么我们下次再见啦~