String类
字符串常用函数(学习2022年6月4日)
一、字符串概述
- 字符串是字符的序列,从某种程度上来说有些类似于字符的数组。
- 在Java中,字符串被当作对象来处理。
- 常量的对象用String类
- 也有StringBuffer类(添加,插入,修改)和StringBiulder类可以使用
二、创建字符串(String的构造函数)
查阅API文档可以发现大量String类的构造函数,摘选其中几个比较常用的进行学习
-
最简单的声明方式:直接双引号加内容。如:
String str = "Hello World!";
-
String() ——创建一个空字符序列的的 String对象。
-
String( String value)——和第一种类似,括号内也是双引号加内容。如:
String str = new String("Hello World!");
-
String( char value[ ] )——因为起那么提到,String有点类似于字符的数组,所以我们可以给构造函数传递一个字符数组char[]来创建字符串。如:
char[] chars = {'H','e','l','l','o'}; String str = new String(chars);
-
String(String original)
——参数可以是另一个字符串,相当于赋值,如:String str1 = new String("Hello"); String str2 = new String(str1); // 相当于 String str3 = str1;
-
String(StringBuffer buffer)
和String(StringBuilder builder)
——参数可以是StringBuffer类和StringBuilder类,可以将其转换为String类型
三、常用方法
具体的方法返回值还是可以参考查阅API文档,也是摘取常用的几个进行总结
-
length()
——用于返回此字符串的长度。 -
charAt(int index)
——用于返回字符串中index位置上的字符,其中index值的范围是0~length-1 -
indexOf(String str)
和 lastindexOf(String str)
——分别查询字符串str在该字符串最早出现的下标,和最晚出现的下标 -
indexOf(int ch)
和lastindexOf(int ch)
还可以搜索int类型,查询的是int对应的字符型char所对应的下标 -
indexOf(...,int fromIndex)
和lastindexOf(...,int fromIndex
)的参数列表还可以加入一个整型int,表示从指定的索引开始搜索-
举例如下:
public static void main(String[] args) { String str1 = "Hello World!"; char ch1 = 'o'; System.out.println((int)ch1); //通过数据类型转换得到字符型H对应的整型为111 System.out.println(str1.indexOf(111)); // 输入整型,返回4 System.out.println(str1.indexOf("o")); // 返回4 System.out.println(str1.indexOf("o",4)); // 返回4 // 注意,在使用fromIndex参数时,返回的下标也是从第一个下标开始算的 System.out.println(str1.indexOf("o",5)); // 返回7 // 注意:在使用fromIndex参数时,检索是从fromIndex开始且包含fromIndex }
-
小结:String 的方法允许我们把字符串当成“字符的数组”,可以进行双向的查询操作
- (下标查字符charAt,字符查下标indexOf,lastIndexOf)
-
concat(String str)
——把新字符串str连接到该字符串的末尾。- 简单的表达用加号”+“表示即可
-
compareTo(String anotherStirng)
——两个字符串比较,返回整型int,如果相同返回0,不同返回非0目前并不清楚用途,感觉功能和equals相同,而且都有
...IgnoreCase
忽略大小写进行比较的的写法 -
equals(String anotherStirng)
——判断两个字符串(对象)是否相等,则可以用此方法。相等则返回 true,不等则返回false。注意,在阿里的规范手册中有提到——Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
正例:“test”.equals(object);
反例:object.equals(“test”);equals
和compareTo
都是比较的作用,除了返回值不一样,还有比较的方式也不同:equals是比较对象,而compareTo是按字典顺序比较两个字符串。
-
replace(char oldChar, char newChar)
——返回:替换字符串所有出现的字符 oldChar为字符newChar 。 -
replace(CharSequence target, CharSequence replacement)
——同样的raplace也可以填入字符串,前面为旧,后面为新。举例:System.out.println(str1.replace('o','i')); // 返回Helli Wirld! System.out.println(str1.replace("ell","abc")); // 返回Habco World!
- 不难发现,这个方法并不会直接改变原字符串的内容,只是返回值进行了替换而已。如果需要改变则需要进行赋值。
-
substring(int beginIndex)
和substring(int beginIndex,int endIndex)
——用来获得字符串中指定范围内的子串。测试如下:System.out.println(str1.substring(3)); //返回lo World! System.out.println(str1.substring(3,7)); // 返回lo W
- 可以发现,是从下标3(且包含3)开始输出,指到下标7(包含7)。即输出的内容包含下标beginIndex到endIndex(且包含它们本身)。
- substring只有一个int参数时,返回的是这个下标开始后的所有字符串
- 注意substring的拼写,S为小写
-
toLowerCase()
和toUpperCase()
——分别是把串中的所有字符转换成小写和大写,和replace一样都不会修改原值 -
valueOf(基本类型)
——把基本类型转换成字符串的形式,返回值为String -
toCharArray()
——将字符串转换为字符数组,返回值为char[] -
isEmpty()
——如果length为0 ,返回true,否则返回false -
endsWith(String suffix)
——判断一个字符串是不是以suffix
结尾,如果是返回true,否则false -
contentEquals(StringBuffer sb)
——提供了一种内置的String和StringBuffer进行比较的函数。举例如下:public class DemoContentEquals { public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("Hello!"); String str1 = "Hello!"; System.out.println(str1.equals(sb1)); // 直接用equals进行比较返回false,需要类型转换才能比较 System.out.println(str1.contentEquals(sb1));// 用contentEquals可以返回true System.out.println(str1.equals(new String(sb1)));//前面提到的类型转换,返回值也是true } }
四、StringBuffer类
1、StringBuffer类
- 线程安全,可变的字符序列。(不同在于 StringBuilder 的方法)
- StringBuffer就像一个String,可以安全地被多个线程使用。
- 字符串缓冲区可以安全地被多个线程使用。
-
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
-
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作所以如果需要对字符串进行修改推荐使用 StringBuffer。
2、 StringBuffer类的构造函数
StringBuffer类的构造函数只指定了4中
StringBuffer()
——声明一个16字符容量的空的StringBufferStringBuffer(int capacity)
——声明一个长度capacity为字符容量的空的StringBufferStringBuffer(String str)
——类似String 可以直接双引号加内容StringBuffer(CharSequence seq)
——看不懂
3、1.2 StringBuffer类的特殊方法
StringBuffer类里也有不少老面孔:如
charAt
/indexOf系列
/length()
/substring
/``replace(但是用法不一样了)`等;
-
append()
——附加、增补某个内容到字符串后面,作用类似加号或者concat();- 这个内容可以是char[]、String、StringBuffer ,还可以是boolean、char、int、float、double、long等基本类型,甚至可以是
Object
参数 - 而且这个方法是对对象本身进行操作
- 这个内容可以是char[]、String、StringBuffer ,还可以是boolean、char、int、float、double、long等基本类型,甚至可以是
-
capacity()
——返回当前容量。 容量是新插入字符可用的存储量,超过此值将进行分配 -
delete(int start, int end)
——删除此序列的子字符串中的字符。 如果start
等于end
,则不作任何更改。 举例如下:public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("Hello World"); System.out.println("旧字符"+sb1); System.out.println("执行delete(3,7)将会删除的字符为:"+sb1.substring(3,7)); sb1.delete(3,7); System.out.println("新字符"+sb1); } // 输出结果为: //旧字符Hello World //执行sb1.delete(3,7)将会删除的字符为:lo W //新字符Helorld
- 不难发现,delete的检索逻辑和substring的一样的
-
replace(int start, int end, String str)
——顾名思义,就是用str替换掉下标start到end的所有字符。举例:public class Demo2 { public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("Hello World"); System.out.println("旧字符"+sb1); System.out.println("执行replace(3,7,\"ABC\")将会替换的字符为:"+sb1.substring(3,7)); sb1.replace(3,7,"ABCDEF"); System.out.println("新字符"+sb1); } } //测试结果 //旧字符Hello World //执行replace(3,7,"ABC")将会替换的字符为:lo W //新字符HelABCorld //执行replace(3,7,"AB")将会替换的字符为:lo W //新字符HelABorld //执行replace(3,7,"ABCDEF")将会替换的字符为:lo W //新字符HelABCDEForld
- 可以发现:replace的替换逻辑是,先删去检索到的范围的字符串,再把新字符串添加到空白的位置,不会因为新字符串是比原字符串长或短所影响。
-
reverse()
——倒转字符串。以上面为例,得到的新字符串为dlroW olleH
-
insert(int offset, ...)
——在指定的下标offset前,插入某个内容。举例:public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("Hello World"); System.out.println("旧字符"+sb1); System.out.println("执行insert插入字符串”ABC后“:"); sb1.insert(3,"ABC"); System.out.println("新字符"+sb1); } //输出结果 //旧字符Hello World //执行insert插入字符串”ABC后“: //新字符HelABClo World
- 注意:insert插入新的内容的位置是在:
下标offset-1
到下标offset
之间。
- 注意:insert插入新的内容的位置是在:
-
setCharAt(int Index,char ch)
——将下标为index的字符替换为ch -
setLength(int newLength)
——**设置字符序列的长度。**如果希望明确地定义字符缓冲区的长度,则可以用此方法。如果newlength大于现在的长度,串尾将补0,如果小于,那么newlength后的字符将丢失。举例:public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("Hello World!"); System.out.println("原长度为"+sb1.length()+",容量为"+sb1.capacity()); System.out.println("原字符串"+sb1); sb1.setLength(5); System.out.println("新长度为:"+sb1.length()+",容量为"+sb1.capacity()); System.out.println("新的字符串"+sb1); sb1.append("我是新的"); System.out.println("新的字符串"+sb1); } //输出结果 原长度为12,容量为28 原字符串Hello World! 新长度为:5,容量为28 新的字符串Hello
- 通过测试可以发现,setLength只能设置一次长度,这个对象后续依然可以插入和增补其他内容。
小结:不难发现,StringBuffer类和Stirng相比,前者的函数是可以直接对自身进行操作,在实际项目中是更方便的。
4、 关于字符容量capacity
-
尝试以下测试,探索容量的变化情况
public class TestStringBuffer { public static void main(String[] args) { StringBuffer sb2 = new StringBuffer(5); System.out.println("刚声明时的容量为:"+sb2.capacity()); sb2.append("Hello World!"); // sb2.append("abc"); // 注意 如果增补的字符串长度不高于容量,则容量不变 System.out.println("第一次加入字符串的容量为:"+sb2.capacity()); System.out.println("第二次加入字符串的长度为:"+sb2.length()); System.out.println("===尝试给sb2增补不同类型的sb1====="); // float sb1 = 1.5F; // 相加后容量为26,长度15 // double sb1 = 1.5; // 相加后容量为26,长度15 // int sb1 = 1; // 相加后容量为26,长度为13 // char sb1 = 123; // 相加后容量为26,长度为13 // String sb1 = "1"; // 相加后容量为26,长度为13 // StringBuffer sb1 = new StringBuffer(5); // 相加后容量为12,长度为12 // sb1.append("1"); // 让sb1增补字符串后 // 相加后容量为26,长度为13 boolean sb1 = true; // 相加后容量为26,长度为16 (输出的结果是Hello World!true System.out.println(sb2.append(sb1)); System.out.println("第二次加入字符串的容量为:"+sb2.capacity()); System.out.println("第二次加入字符串的长度为:"+sb2.length()); } }
输出结果为: 刚声明时的容量为:5 第一次加入字符串的容量为:12 第二次加入字符串的长度为:12 ===尝试给sb2增补不同类型的sb1===== Hello World!true 第二次加入字符串的容量为:26 第二次加入字符串的长度为:16
-
其实不难发现,字符容量一直在变化,并不是固定的
-
注意 ,在如果StringBuffer声明了容量后,增补的字符串长度不高于容量,则容量不变
思考1:capacity的含义和概念?
- 有查到容量的概念:容量是新插入字符可用的存储量,超过此值将进行分配
- 具体意义不明
思考2:在StringBuffer类里,capacity和length有什么不一样?/ 字符容量和字符长度有什么不一样呢?
- 尝试附加不同的基本类型,但是发现新的字符容量都是加14
- 尝试加入空的StringBuffer类型,发现字符容量不变,但是如果这个StringBuffer类型不为空,则字符容量还是会加14
- 具体差别不明
6、StringBuilder类
-
它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
-
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
-
然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
其实两者的方法和用法都类似,就不赘述了
五、 基本数据类型 的封装类
1、基本数据类型都有对应的封装类
- boolean->Boolean
- char->Character
- byte->Byte
- short->Short
- int ->Integer
- long->Long
- float->Float
- double->Double
1.1 基本类型封装类的基本用法
封装类 和 基本类型 互相转换
基本类型名Value(封装类)
——封装类转基本类型……比如:doubleValue(),返回的就是double数据类型- 这个函数可以用于不同数据类型之间的转换
- 构造函数可以直接实现基本类型转封装类的转换
- 还有一种方法,封装类名.valueOf()方法可以实现转换。如
Double.valueOf(d1)
可以将double类型的d1转换为Double封装类的变量
2、 String类 和 基本类型 的转换
封装类 转 字符串String (实际上是String 的方法)
-
String.valueOf(基本类型)
——返回值为String,效果相当于把基本数据类型转换为String。举例如下public static void main(String[] args) { Double dB = 1.234; double db = dB.doubleValue(); //将封装类转换成基本类型 String str1 = String.valueOf(db); //是静态方法,可以不用实例化 }
- 查看源码可以发现
valueOf()
方法是静态声明的,所以调用这个方法是不需要实例化对象的,直接类名.方法名
就可以调用了
- 查看源码可以发现
3、 一些其他方法
这些封装类还有一些函数可以调用,先记录几个看起来有用的函数
-
compare(基本数据类型d1,基本数据类型d2)
——【静态方法】比较两个基本类型,返回值为int整型- 如果d1在数字上等于d2的值,返回0;如果d1在数值上小于d2返回值小于0 ; 如果d1在数值大于d2 ,则返回值大于0
- 特殊的
Boolean.compare(b1,b2)
:(true,false)返回1;(false,true)返回-1;相同返回0
-
max(基本数据类型d1,基本数据类型d2)
和min(基本数据类型d1,基本数据类型d2)
——【静态方法】,比较两个数据类型的大小,返回的值是对应的数据类型 -
sum(d1,d2)
——【静态方法】两个数据类型相加,返回的也是这个数据类型- Boolean类里没有这个方法