五、字符串
1. 所属的包是java.lang包 不用导入
2. 找寻构造方法创建对象
String str = "abc";
//直接将字符串常量赋值给str (字符串是从字符串常量池中取出来的)
String str = new String();
//无参数构造方法创建空的对象,用处不大
String str = new String("abc");
//带string参数的构造方法创建对象
String str = new String(byte[] )
//将数组中的每一个元素转化成对应的char 组合成String
String str = new String(char[] )
//将数组中的每一个char元素拼接成最终的String
String是一个非常特殊的引用数据类型,可以像基本类型一样,创建,赋值。
byte[] value = new byte[]{65,97,48};
String str = new String(value);
System.out.println(str);//ell
char[] value1 = {'h','e','l','l','o'};
String str1 = new String(value1,1,3);
System.out.println(str1);// ell
3. String类的不可变特性
String类中包含一个private final char[] value;
体现在两个地方:长度及内容
长度—>final修饰的数组 数组长度本身不变 final修饰数组的地址也不变
内容—>private修饰的属性 不能在类的外部访问
疑问:为什么内容不可变,却还有那么多方法改变了字符串的内容 的解释
所以需要注意的是,任意一种改变了字符串的内容或者长度的方法,实际上都是新建立了一个字符串,原先的字符串还存在在那里,我们新建立的也存在在那里,如果你想改变原字符串,那么就要让原字符串的引用指向新的字符串。比如:String str="+123"
如果你写str.substring(1)
那么str还是+123,如果你想改变这个str,那么你应该写的是str = str.substring(1)
,此时的str指向了新的字符串,即为123。
4. String类中常用的方法 :
第一梯队(重写)
equals hashCode compareTo toString
第二梯队(常用)
charAt() codePointAt()
indexOf() lastIndexOf()
substring() split() replace()
length() concat() contains(); trim();
getBytes() toCharArray() matches()
第三梯队(一般)
toUpperCase() toLowerCase()
startsWith() endsWith();
isEmpty();
包装类中的方法:
也就是 String.valueOf() 这个参数多载的方法
有下列几种
String.valueOf(boolean b) : 将 boolean 变量 b 转换成字符串
String.valueOf(char c) : 将 char 变量 c 转换成字符串
String.valueOf(char[] data) : 将 char 数组 data 转换成字符串
String.valueOf(char[] data, int offset, int count) :
将 char 数组 data 中 由 data[offset] 开始取 count 个元素 转换成字符串
String.valueOf(double d) : 将 double 变量 d 转换成字符串
String.valueOf(float f) : 将 float 变量 f 转换成字符串
String.valueOf(int i) : 将 int 变量 i 转换成字符串
String.valueOf(long l) : 将 long 变量 l 转换成字符串
String.valueOf(Object obj) : 将 obj 对象转换成 字符串, 等于 obj.toString()
-
boolean = equals(Object obj);
//继承自Object 重写啦,比较两个字串中的字面值是否相等。刚才查看内存的时候可以参考。
public static void main(String[] args){
//String类 "abc"对象 常量区
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s1==s2);//true
System.out.println(s1==s3);//false
System.out.println(s3==s4);//false
System.out.println(s1.equals(s2));//true String类将继承自Object中的equals方法重写啦
System.out.println(s1.equals(s3));//true 将原有比较==的方式改为比较字符值
System.out.println(s3.equals(s4));//true
}
= = == == equals方法的区别
= = == ==可以比较基本类型 可以比较引用类型
比较基本类型比较值; 比较引用类型比较地址
equals只能比较引用类型(方法)
默认比较地址this==obj
如果想要修改其比较规则 可以重写equals方法
通常重写equals方法时会伴随着重写hashCode方法
比如String类 比如Integer
int = hashCode();
//继承自Object 重写啦,将当前字符串的每一个char元素拆开,乘以31求和。通常重写equals方法时会伴随着重写hashCode方法。
str.hashCode();// 内存地址调用一个本地的native方法进行计算
//"abc" h=0
//h = (0*31+97)
//h = (97)*31+98
//h = ((97)*31+98)*31+99
-
int = compareTo(String str);
//实现自Comparable接口, 按照字典(Unicode编码)索引的顺序比较
String str1 = "abc";
String str2 = "ab" ;
//abc-->0 abd-->-1 abe-->-2 abb-->1 aba-->2 a-->2 ab-->1
System.out.println(str1.compareTo(str2));
//按照两个字符串长度较短的那个作为比较循环的次数
//挨个比较元素 str1[i]-str2[i] 循环内如果有结果,就输出
//如果循环过后发现所有的字符都一样 len1-len2
//返回0表示两个字符相等
-
String = toString();
//继承自Object ,重写啦 ,不再输出类名@hashCode
而是输出: 字符串中的字面值 -
char = charAt(int index);
//“abc” 0–>a
//返回给定index对应位置的那个char值
int = codePointAt(int index);
//“abc” 0–>97
//返回给定index对应位置的那个char所对应的code码
String str = "abc";
char c = str.charAt(0);
System.out.println(c);
int = length();
//返回字符串的长度String = concat(String);
//将给定的字符串拼接在当前字符串之后
String str = "abcdef";
//String对象 (字符串常量池) value属性char[]
//长度不能改变 数组地址不让改变 数组属性私有的我们操作不了
//str.concat("g"); //如果是这一句,那么输出的是abcdef,体现的是字符串的不可变特性
str = str.concat("g");//abcdefg
//创建一个新的String对象 (字符串常量池) value属性 7个
//刚才那个String对象value值依次取出来 存入新对象的value属性 g放在后面
System.out.println(str);//abcdefg
//String的不可变特性
String str = "a"+"b"+"c"+"d";//数学计算 拼接符号
System.out.println(str);//abcd
// 过程中产生了几个String对象? 字符串常量池7个
//1对象-->value[] a "a"
//2对象-->value[] b "b"
//3对象-->value[] {a,b} "ab"
//4对象-->value[] c "c"
//5对象-->value[] {a,b,c} "abc"
//6对象-->value[] d "d"
//7对象-->value[] "abcd"
contact性能比“+”性能更好些,但是实际上,开发中若遇到频繁的拼接字符串—>通常使用StringBuilder/StringBuffer
8. boolean = contains(CharSequence s);
判断给定的s是否在字符串中存在。
String str = "abcdefg";
//判断此字符串中是否含有a
boolean value = str.contains("ag");
System.out.println(value); //false 元素得连着的
startsWith(String prefix);
endsWith(String suffix);
判断此字符串是否已xx开头/结尾,返回值boolean类型。
String str = "TestString.java";
boolean value = str.endsWith(".java");
System.out.println(value); //true
- 将当前的字符串转化成数组的两个方法,只有返回值不同
byte[] = getBytes();
—> getBytes(String charsetName);输出byte类型的数值,要想看具体内容可以进行强制类型转换。
char[] = toCharArray();
“我爱你中国” char[] ‘我’ ‘爱’ ‘你’ ‘中’ ‘国’
但是如果你用byte[]就不可以,因为byte装不下。
String str = "abcdefg"; //我爱你中国
byte[] b = str.getBytes();
for(byte v:b){
System.out.println(v); //byte
}
for(byte v:b){
System.out.println((char)v); //byte
}
//97 98 99 100 101 102 103
//abcdefg
//如果是我爱你中国,就会乱码。
//如果直接用char,返回值直接就是char
char[] c = str.toCharArray();
for(char v:c){
System.out.println(v);
}//abcdefg //我爱你中国因为char能够存下汉字
int index = indexOf(int/或者String str [不写,或者int fromIndex] );
fromIndex从哪开始,但是不管你从哪开始找,返回的位置是从头开始数的。
找寻给定的元素在字符串中第一次出现的索引位置,,返回值是位置,若字符串不存在则返回-1。
lastIndexOf(int/String str , [int fromIndex]);
找寻给定的元素在字符串中最后一次出现的索引位置,若不存在则返回-1。
String str = "abcdefgabcm";
int index = str.indexOf("b"); //1
// int index = str.indexOf("m",3); //10
System.out.println(index);//1 不论从哪儿开始找寻 返回的index都是相对于整个String的
String str = "abcdefgabcm";
// int index = str.lastIndexOf("m"); //10
int index = str.lastIndexOf("m",3); //-1 从3号索引往前找
System.out.println(index);//-1 不论从哪儿开始找寻 返回的index都是相对于整个String的位置
boolean = isEmpty();
判断当前字符串是否为空字符串 (length是否为0)。
注意: 与null之间的区别。
// String str = ""; //true
String str = null;//异常NullPointerException
boolean value = str.isEmpty();
System.out.println(value); //true
- 将给定的字符串替换成另外的字符串
replace();
凡是出现的都换掉。
replaceAll();
和repalce()差不多,没啥不一样。
replaceFirst();
换第一次出现的那个字串。
String str = "你好啊好啊";
// str = str.replace('好','美'); //你美啊美啊
// str = str.replace("好啊","加油"); //你加油加油
str = str.replaceFirst("好","美"); //你美啊好啊
System.out.println(str);
String[] = split(String regex [,int limit限度界限]);
按照给定的表达式将原来的字符串拆分开的,限度表示拆成几段。返回是String类型的数组。
比如字符串数组长度为5,拆成limit=2,那么就是原字符串数组中的第一个元素是第一个元素,原字符串数组中的剩余元素作为新数组的第二个元素。
String str = "a-b-c-d";
String[] value = str.split("-",3); //3:拆成3段
for(String v:value){
System.out.println(v);
} //a b c-d
String = substring(int beginIndex [,int endIndex]);
将当前的字符串截取一部分。
从beginIndex开始至endIndex结束 [beginIndex,endIndex);
若endIndex不写 则默认到字符串最后。
String str = "abcdefgh";
// str = str.substring(3);//defgh 从3号索引开始一直到最后
str = str.substring(3,5);//de 从3号索引开始到5号索引结束 [3,5)
System.out.println(str);
String = toUpperCase();
String = toLowerCase();
将全部字符串转换成大写/小写。大小写也可以截取:
String firstLetter = word.substring(0,1).toUpperCase();//首字母截取 变大写
String otherLetters = word.substring(1);//其余的其他字母
String = trim();
去掉字符串左右多余的空格,中间的不去掉,返回字符串,自己接收。
5. 习题
1.设计一个方法 将字符串反转 ok–>ko
2.设计一个方法 将给定字符串的正序和反序进行连接 ok–>okko
3.设计一个方法 判断给定字符串是否是回文 abccba abcba
4.设计一个方法 将给定的字符串右位移x位置 (helloworld,2) --> ldhellowor
5.设计一个方法 寻找若干字符串中最长的那个 ab,abc,abcd—>abcd
6.设计一个方法 统计给定字母在字符串中出现的次数 “this is a test of java”,“a”—>3
7.设计一个方法 将给定的字符串每一个首字母大写 “this is a test of java”—>“This Is A Test Of Java”
8.设计一个方法 获取给定字符串中的全部数字 “za1o1zbp24tcq”—>1124
- 设计一个方法 将字符串反转 ok–>ko
//1.设计一个方法 将字符串反转 ok-->ko
// 是否需要参数 String 是否需要返回值 String
public String reverse(String str){
//将str变化成数组
char[] value = str.toCharArray();
//数组头尾互换
for(int i=0;i<value.length/2;i++){
char temp = value[i];
value[i] = value[value.length-1-i];
value[value.length-1-i] = temp;
}
//数组组合成字符串 返回
return new String(value); //字符串有4中构造方法,其中一种就是用字节数组char[] 组成字符串
注意:String类型有4种构造方法,可以直接用char[]数组 ,组成String。
2.设计一个方法 将给定字符串的正序和反序进行连接 ok–>okko
//2.设计一个方法 将给定字符串的正序和反序进行连接 ok-->okko
// 是否需要参数String 是否需要返回值 String
public String reverseAndConcat(String str){
// //1.将str反转
// String value = this.reverse(str);
// //2.str之后拼接 反转过来的字串
// String result = str.concat(value);
// //3.将最终结果返回
// return result;
return str.concat(this.reverse(str));
类中的某个方法 需要 调用自己类中的其他方法,记得用this啊!
- 设计一个方法 判断给定字符串是否是回文 abccba abcba
//3.设计一个方法 判断给定字符串是否是回文 abccba abcba
// 是否需要参数String 是否需要返回值 boolean
public boolean isPalindrome(String str){
//传递进来的str先反转
//用str与反转之后的字符串进行比较
//如果完全一致 证明是回文
if(this.reverse(str).equals(str)){
return true;
}
return false;
}
自己就没有想到,反转之后比较是否相同。自己想的是头和尾一次比较,好笨啊。
- 设计一个方法 将给定的字符串右位移x位置
(helloworld,2) --> ldhellowor
//4.设计一个方法 将给定的字符串右位移x位置 (helloworld,2) --> ldhellowor
// 是否需要参数String,count 是否需要返回值String
public String moveToRight(String str,int count){
//if(count<0){
//自定义异常 告知count不合理
// }
if(count>str.length()){
count %= str.length();
}
//截取
//前半部分
String begin = str.substring(0,str.length()-count);//拼接时放在后面
//后半部分
String end = str.substring(str.length()-count);//拼接时放在前面
//拼接以后返回
return end.concat(begin);
}
记得拆分函数啊。
- 设计一个方法 寻找若干字符串中最长的那个
ab,abc,abcd—>abcd
//5.设计一个方法 寻找若干字符串中最长的那个 ab,abc,abcd--->abcd
// 是否需要参数 若干个String... 是否需要返回值String
public String findMaxLengthString(String...strs){
String result = strs[0];//第一个字符串存起来
int maxLength = strs[0].length();//第一个字符串的长度
for(int i=1;i<strs.length;i++){
if(strs[i].length()>maxLength){
maxLength = strs[i].length();
result = strs[i];
}
}
return result;
}
若干个
String...strs
,有自己的长度,strs[0]
则表示第0位的字符串。
- 设计一个方法 统计给定字母在字符串中出现的次数 “this is a test of java”,“a”—>3
//6.设计一个方法 统计给定字母在字符串中出现的次数 "this is a test of java","a"--->3
// 是否需要参数 String char 是否需要返回值int
public int letterExistCount(String str,char letter) {
return str.length() - str.replace(String.valueOf(letter), "").length(); //方法1
//替换为空:this is a test of java将a替换为""结果为this is test of jv,
//原来的长度减去新的长度就可以啦
//方法2
// int count = 0;//记录找到的个数
// for(int i=0;i<str.length();i++){
// if(str.charAt(i)==letter){
// count++;
// }
// }
// return count;
}
方法1,没有想到。将带检查的字母替换为“”然后用原来的长度减去新的长度就可以了。注意字符串的长度计算的时候,空格也是占一位的。
将char类型变成String类型的方法:String.valueOf(letter)
- 设计一个方法 将给定的字符串每一个首字母大写 “this is a test of java”—>“This Is A Test Of Java”
//7.设计一个方法 将给定的字符串每一个首字母大写
// "this is a test of java"--->"This Is A Test Of Java"
// 是否需要参数 String 是否需要返回值String
public String firstLetterToUpperCase(String str){
String result = "";//最终拼接完整字符串
//将完整的字符串按照空格拆分成好多单词 split
String[] value = str.split(" ");
//循环处理每一个单词 截取首字母-->大写 截取其余的字母 整体拼接
//每一次的单词拼接成一个完整的字符串 返回 a.append(b)
for(int i=0;i<value.length;i++){
String word = value[i];//获取每一个单词
String firstLetter = word.substring(0,1).toUpperCase();//首字母截取 变大写
String otherLetters = word.substring(1);//其余的其他字母
result = result.concat(firstLetter.concat(otherLetters)+" ");//注意String的不可变特性
}
return result.trim();//去掉最后多余的那个空格
}
toUpperCase
是将所有的字母都大写,我们如果只想将首字母大写,只能截取首字母单独大写,然后后面的在截取出来,然后两部分再拼接起来。
- 设计一个方法 获取给定字符串中的全部数字 “za1o1zbp24tcq”—>1124
//8.设计一个方法 获取给定字符串中的全部数字 "za1o1zbp24tcq"--->1124
// 是否需要参数 String 是否需要返回值int
public int findNumber(String str){
String result = "";
//循环找寻字符串中的每一个 字符
//判断当前找到的字符是否是 数字 '0'---'9' 48--57
for(int i=0;i<str.length();i++){
int code = str.codePointAt(i);//每一个字符对应的code码
if(code>=48 && code<=57){
result += (char)code;
}
}
//将找到的数字返回
return Integer.parseInt(result);//int value = new Integer(result);
}
int code = str.codePointAt(i)
获得字符串中的每个字符的编码。
6. StringBuffer ; StringBuilder
StringBufferd支持并发操作,线性安全的,适 合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。
String str = “abc”;
内存存储 "abc"对象 char[] value
String不可变特性 private final char[] value;
频繁的修改其内容的时候 性能很不好
所以提出了:StringBuffer ; StringBuilder
(1)StringBuilder类不一定需要 是为了避免String频繁拼接修改字符串信息的时候才用的
底层数组是可变的 提高了性能
(2)常用方法
与String类不同的独有方法
append() insert() delete() deleteCharAt() reverse()
与String类相同的方法
length() charAt() codePointAt() indexOf() lastIndexOf()
substring() replace()名字相同 用法不一致
不是很常用的方法
ensureCapacity() capacity() setLength() trimToSize(); setCharAt();
- 所属的包 java.lang包
- 继承AbstractStringBuilder 间接继承 Object
实现接口Serializable,CharSequence,Appendable
StringBuffer/StringBuilder没有compareTo
方法
StringBuffer/StringBuilder含有一个String没有的方法append();
拼接
append方法拼接速度比+和contact都要快好多好多,验证一下:
String str = "a";
long time1 = System.currentTimeMillis();
for(int i=1;i<=200000;i++){
// str+="a";//方法1 + 拼接:利用+拼接 14588
str = str.concat("a"); //方法2:contact拼接 8523
}
long time2 = System.currentTimeMillis();
System.out.println(time2-time1);
使用append方法:
StringBuilder builder = new StringBuilder("a");//17
long time1 = System.currentTimeMillis();
for(int i=1;i<=200000;i++){
builder = builder.append("a");//7毫秒
}
long time2 = System.currentTimeMillis();
System.out.println(time2-time1);
- 特性
可变字符串 char[] value; 动态扩容 - 对象的构建
//无参数构造方法 构建一个默认长度16个空间的对象 char[]
StringBuilder builder = new StringBuilder();
//利用给定的参数 构建一个自定义长度空间的对象 char[]
StringBuilder builder = new StringBuilder(20);
//利用带String参数的构造方法 默认数组长度字符串长度+16个
StringBuilder builder = new StringBuilder("abc");
- StringBuilder中常用的方法
最主要的方法append()
频繁的拼接字符串的时候使用此方法 提高性能
ensureCapacity(int minimumCapacity)
确保底层数组容量够用
capacity();
//字符串底层char[]的容量
length();
//字符串有效元素个数(长度)
setLength();
//设置字符串的有效元素个数
char = charAt(int index);
int = codePointAt(int index);
String = substring(int start [,int end]);
注意需要接受返回值,看见截取出来的新字符串效果
StringBuilder = delete(int start [,int end]);
StringBuilder类中独有的方法String类没有。将start到end之间的字符串删掉,不用接受返回值就看到效果啦。
StringBuilder = deleteCharAt(int index);
String类中没有的方法,独有方法。将给定index位置的某一个字符删除掉啦
int = indexOf(String str [,int fromIndex]);
int = lastIndexOf(String str [,int fromIndex])
找寻给定的str在字符串中第一次出现的索引位置 带重载 则从某一个位置开始找
insert(int index,value);
将给定的value插入在index位置之上
replace(int start,int end,String str);
将start和end之间的部分替换成str
builder.replace(2,5,"zzt");
setCharAt(int index,char value);
将index位置的字符改成给定的value
toString()
将StringBuilder对象 构建成一个string对象 返回
trimToSize()
将数组中无用的容量去掉 ,变成length长度的数组
7. 正则表达式
正则表达式regex:一个带有一定规律的表达式;匹配字符串格式的
正则表达式通常的作用如下:
- 字符串的格式校验
String类中提供 的一个方法boolean = str.matches("regex");
- 字符串的拆分及替换
String类中提供的方法replace
和split
- 字符串的查找
Pattern模式;Matcher匹配器
//第一个字母必须是a 第二个字母是abc其中的一个
// a[abc]中括号表示必须在这几个当中选一个
boolean result1 = str.matches("a[abc]");
System.out.println(result1);
//第一个字母必须是a 第二个字母是非abc任意的其他一个
boolean result2 = str.matches("a[^abc]");
System.out.println(result2);
//第一个必须是a,第二哥必须是这些字母A到Z以及a到z中的一个
boolean result3 = str.matches("a[A-Za-z]");
System.out.println(result3);
//其他的写法,去正则化表达式中自行找吧
如下的所有都用来描述字符的信息
[abc] abc其中的一个
[^abc] 不能是abc其中的一个 其他都可以
[a-zA-Z] 表示必须是这两个范围内的
[a-z&&[^bc]] 表示a-z其中的一个但不能是b和c
| 或者
. 代表任意一个字符
\d digit数字 [0-9]
\D 非数字 [^0-9]
\s space留白 一个空格 一个回车 一个换行。。。
\S 非留白
\w word单词 [0-9A-Za-z] 数字或字母都可以
\W 非单词 [^0-9A-Za-z]
如下的所有都用来描述字符出现的次数
? 0-1次 [0-9]?
* 0-n次
+ 1-n次
{n} 固定n次
{n,} 至少出现n次
{m,n} m-n次