目录
(1)s1.charAt(index) index:下标,返回字符串的值
(2)s1.indexOf(ch) 从前往后找,返回ch第一次出现时的下标,没有就返回 -1
(3)s1.indexOf(ch,from) 从下标from开始往后找,返回ch第一次出现时的下标,没有就返回 -1
(4)s1.indexOf(str) 在字符串中找字符串str,找到返回下标
(5)s1.indexOf(str,from) 从from下标开始往后找字符串str,找到返回下标
(6)s1.lastIndexOf(ch) 从后往前找,返回ch第一次出现的下标
(7)s1.lastIndexOf(ch,from) 从from开始往前找,返回ch第一次出现的下标
(8)s1.lastIndexOf(str) 从后往前找字符串str,找到返回第一次出现的下标
(9)s1.lastIndexOf(str,from) 从from开始往前找,找到返回第一次出现的下标
(1)String.valueOf(各种类型的变量) —— 其他类型转化成字符串
(4)s1.toCharArray() —— 字符串转字符数组【这个方法很重要】
(5)字符数组转字符串 —— 把数组直接扔过去就变成了字符串
(2)s1.contains(str) —— 字符串s1中是否包含字符串str,返回true 或 false
(3)s1.endsWith(str) —— 判断字符串s1是否以字符串str结尾,返回true 或 false
(4)s1.startsWith(str) —— 判断字符串s1是否以字符串str开始,返回true 或 false
1. StringBuilder和StringBuffer的特点:
2. StringBuilder和StringBuffer的方法:
3. String、StringBuilder和StringBuffer的不同点:
4. StringBuilder类型的对象和String类型的对象,如何相互转换?
一. 字符串的定义
1. String类中有两个成员:value数组和hash。String内部并不存储字符串本身,字符串保存在char类型的字符数组value中
2. 字符串不以‘\0’结尾
3. 使用 s1.length() 输出字符串的长度
二. String类中的常用方法
String类中的方法,基本上返回的都是一个新的字符串对象,不是在原来上做出改变
1. 比较两个字符串是否相等(返回值是boolean类型)
(1)比较两个字符串是否相等 —— s1.equals(s2)
(2)忽略大小写比较两个字符串是否相等 —— s1.equalsIgnoreCase(s2)
2. 比较两个字符串的大小(返回值是int类型)
因为String类实现了Comparable<String>接口,所以String一定重写了compareTo方法
(1)比较两个字符串的大小 —— s1.compareTo(s2)
(2)忽略大小写比较两个字符串的大小 —— s1.compareToIgnoreCase(s2)
3. 字符串查找
(1)s1.charAt(index) index:下标,返回字符串的值
(2)s1.indexOf(ch) 从前往后找,返回ch第一次出现时的下标,没有就返回 -1
(3)s1.indexOf(ch,from) 从下标from开始往后找,返回ch第一次出现时的下标,没有就返回 -1
(4)s1.indexOf(str) 在字符串中找字符串str,找到返回下标
(5)s1.indexOf(str,from) 从from下标开始往后找字符串str,找到返回下标
(6)s1.lastIndexOf(ch) 从后往前找,返回ch第一次出现的下标
(7)s1.lastIndexOf(ch,from) 从from开始往前找,返回ch第一次出现的下标
(8)s1.lastIndexOf(str) 从后往前找字符串str,找到返回第一次出现的下标
(9)s1.lastIndexOf(str,from) 从from开始往前找,找到返回第一次出现的下标
4. 转化
(1)String.valueOf(各种类型的变量) —— 其他类型转化成字符串
(2)字符串转化成其他类型
(3)字符串大小写转化
小写转大写:s1.toUpperCase()
大写转小写:s1.toLowerCase()
(4)s1.toCharArray() —— 字符串转字符数组【这个方法很重要】
(5)字符数组转字符串 —— 把数组直接扔过去就变成了字符串
5. 字符串替换 —— 返回的是一个新的字符串
(1)s1.replace('oldChar','newChar') 字符oldChar全部替换成newChar
(2)s1.replace(" "," ") 字符串全部替换
(3)s1.replaceAll(" "," ") 字符串全部替换
(4)s1.replaceFirst(" "," ") 替换第一个出现的
6. 字符串拆分
(1)s1.split(拆分符号)
(2)s1.split(拆分符号,拆分成几份)【拆分成几份,即数组中有几个元素,当然不能拆也不能硬拆】
特殊:. \ | * + 等 都得加上转义字符
如: . 【\ 去转义这个 . 了,那么这个 \ 怎么办,还得需要一个 \ 来转义】所以是 \\.
【每个\都需要\去转义,s2里面就有两个\,所以是 \\\\】
\不可能单独存在,因为它会和后面形成转义,就不是\了,只能\\这样存在。\\其实就是一个\。
要是想以一个\进行拆分,可以下面这样,因为是拆分失败,就只能把s1的内容原样输出啦。
如果一个字符串中有多个分隔符,可以用"|"作为连字符
多次拆分:
7. 字符串截取(用的非常多)
(1)s1.substring(index) —— 从index下标开始截取
(2)s1.substring(beginIndex,endIndex) —— 从beginIndex截取到endIndex,左闭右开
8. 字符串的其他方法
(1)s1.trim() —— 去掉字符串左右两边的空格
(2)s1.contains(str) —— 字符串s1中是否包含字符串str,返回true 或 false
(3)s1.endsWith(str) —— 判断字符串s1是否以字符串str结尾,返回true 或 false
(4)s1.startsWith(str) —— 判断字符串s1是否以字符串str开始,返回true 或 false
三. 字符串常量池
1. 字符串常量池
字符串常量池,是存放在堆中的一块区域。底层是一个StringTable的哈希表
只要是双引号引起来的,首先会去字符串常量池检查有没有相同的 ,如果字符串常量池中有,拿常量池的,如果没有,就把字符串存到常量池中,常量池中只存一份。
如:
题目一:
对于s1来说,常量池中没有“hello”这个字符串,所以会在常量池中存一份。给s2赋值“hello”时,常量池中已经存在该字符串了,取的是常量池的同一份,所以结果为true。
题目二:
对于s1来说,常量池中没有“hello”这个字符串,所以会在常量池中存一份。同时,自己new了一个String对象,value中存的是常量池的“hello”的地址(0x12)。给s2赋值“hello”时,常量池中已经存在该字符串了,所以不会再存一遍了,同时,自己又new 了一个String对象,value中存的还是0x12。只不过,s1和s2都是新new了String对象,里面存的是新的地址,所以结果为false。但是,它们value中存的值都是相同的,都指向同一份“hello”。
总结:
构造字符串时,最好不要new一个对象,直接使用字符串常量给引用变量赋值就行,由于字符串常量池的存在,直接赋值的效率更高,而且更节省空间。
2. String类对象实例化底层
(1)
(2)
(3)
会将字符数组ch拷贝一份
总结:
(1)会存到常量池
(2)会存到常量池,堆上还会new一个String对象
(3)堆上new一个数组,对数组进行一次拷贝,然后new一个String对象,让value数组指向拷贝好的数组。
3. intern方法
该方法的作用是当常量池不存在这个对象的时候,会将创建的此对象添加到常量池中。
没用intern之前,s1的对象并不在常量池之中,而是拷贝的ch指向的字符数组。如下图:
所以要想输出true,s1的对象需要在常量池中存一份。
s1调用intern,会将s1所指的对象放到常量池中。那么给s2赋值“abc”时,常量池中已经有"abc"对象了,所以用的是同一份,如下图:
四. 字符串的不可变性
字符串是不可变的,对字符串进行操作,不会在原字符串上进行改变,而是会返回一个新的字符串对象。
五. 字符串修改
字符串是不能修改的,每次修改都会创建新的对象,效率非常低下。
我们通过汇编可以看到,这几行代码,其实创建了许多StringBuilder对象去拼接字符串
还原出来就是下面这个代码:
六. StringBuilder和StringBuffer
StringBuilder和StringBuffer new对象调用构造方法时,会在原来字符串的基础上后面多16个空格。
调用StringBuilder类中的toString方法后,返回一个新的对象,count就是字符串的长度,这个新对象没有多余的16个空格啦。于是StringBuilder就变成String类了。
1. StringBuilder和StringBuffer的特点:
(1)是一个类
(2)不能直接赋值,需要new对象
new对象调用这个构造方法,会在原来字符串的基础上多16个空格,字符串变长了。
(3)StringBuilder和StringBuffer是可变的,拼接后返回的还是这个对象,不会产生新的对象
有返回值,却不需要接收。因为返回的还是这个对象(this),在自身进行了修改。
(4)StringBuilder重写了toString方法,StringBuffer也重写了toString方法
System.out.println(stringBuilder);
首先,会调用StringBuilder重写的toString方法,返回String类型的一个新对象。(假设起名s1)
【调用StringBuilder类中的toString方法:count就是字符串的长度,这个新对象没有多余的16个空格啦】
然后,s1会调用String类中的toString方法,返回this。
所以,最后输出的是字符串“hello”。
2. StringBuilder和StringBuffer的方法:
append:字符串拼接
delete:删除指定范围内的字符,左闭右开
reverse:字符串逆置
3. String、StringBuilder和StringBuffer的不同点:
(1)String的内容不可修改,StringBuilder和StringBuffer的内容可以修改
(2)StringBuffer和StringBuilder大部分功能是相似的
(3)StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
synchronized: 多线程情况下,用来保证线程的安全
4. StringBuilder类型的对象和String类型的对象,如何相互转换?
(1)StringBuilder转String: 调用StringBuilder中的toString方法
(2)String转StringBuilder: 利用StringBuilder的构造方法或append方法
5. 以下分别创建了多少个对象(常量池里都没有)
数组的那个对象不分开算,整体算一个对象
(1):2个,常量池一个,new了一个
(2):6个,常量池2个(“a”和“b”),new的两个,它们两个拼接生成了一个StringBuilder对象,最后,赋值给String类型,会调用StringBuilder的toString方法,toString方法会返回一个新的String对象,即又new了一个对象。总共6个。
七. String类oj题
1. 字符串中的第一个唯一字符
2. 最后一个单词的长度
(1)lastIndexOf(查找返回下标)(2) split方法(拆分)(3)charAt(返回值)
3. 检测字符串是否为回文
(1)StringBuilder的reserve方法(2)双指针
Character类的静态方法:
Character.isDigit(char c) —— 判断字符c是否是数字字符
Character.isletter(char c) —— 判断字符c是否是字母字符
Character.isLowerCase(char c) —— 判断字符c是否是小写字母字符
Character.isUpperCase(char c) —— 判断字符c是否是大写字母字符
Character.isLetterorDigit(char c) —— 判断字符c是否是字母或数字字符
4. 字符串中的单词数
(1)split方法
5. 转换成小写字母
(1)toCharArray方法,转成字符数组(2)自己定义一个字符数组(3)使用StringBuilder,append方法
6. 单词规律
(1)用toCharArray方法和split方法,放到数组,暴力遍历