文章目录
- 前言
- 1.String类的重要性
- 2.常用方法
- 2.1.字符串的创建
- 2.2.字符串的比较
- 2.2.1.==比较是否引用同一个对象
- 2.2.2.boolean equals(Object anObject) 方法:
- 2.2.3.int CompareTo(String s)
- 2.2.4.int compareToIgnoreCase(String str) 方法:
- 2.3.字符串的查找
- 2.4.字符串的转化
- 2.4.1.数值和字符串之间转化
- 2.4.2.大小写转化
- 2.4.3.字符串转化为字符数组
- 2.4.4.格式化
- 2.5.字符串的替换
- 2.6 字符串拆分
- 2.7 字符串截取
- 2.8.其他操作方法
- 2.9.字符串的不变性
- 3. StringBuilder和StringBuffer
- 3.1 StringBuilder的介绍
- 3.2 面试题:
- 4.String OJ题
前言
上一篇我们学习了创建一个图书管理系统,更加深入地复习类和对象、面向对象,继承,多态以及接口等相关内容,今天我们学习一个新的内容—String类型
1.String类的重要性
在C语言中已经涉及到字符串了,但是在C语言中没有字符串,要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。
2.常用方法
2.1.字符串的创建
主要有三种:
1.String 变量名=“内容”;(注意是双引号)
2.String 变量名=new String(“内容”);
3.利用字符数组,创建字符串
public static void main(String[] args) {
String str1="hello";
String str2=new String(" world");
char[]chars={'a','b','c','d'};
String str3=new String(chars);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
}
2.2.字符串的比较
字符串的比较主要有4种方法(==,equals,compareTo,compareToIgnoreCase)
2.2.1.==比较是否引用同一个对象
public static void main(String[] args) {
String str1=new String("hello");
String str2=new String("hello");
String str3=str1;
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str2==str3);
}
为什么?
我们画个图来解释一下
由此可知,==是比较两个String类型的地址,那么如果我们只想比较两个String类型中值是否一样,那么就要使用equals方法
2.2.2.boolean equals(Object anObject) 方法:
按照字典序比较字典序:字符大小的顺序
String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照如下规则进行比较,比如: s1.equals(s2)
public static void main(String[] args) {
String str1=new String("hello");
String str2=new String("hello");
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
System.out.println(str2.equals(str3));
}
2.2.3.int CompareTo(String s)
如果我们要比较两个字符串的大小,那么就不能使用equals方法,而要使用compareTo方法。
public static void main(String[] args) {
String s="abcd";
String s1="agada";
int ret=s.compareTo(s1);
System.out.println(ret);
}
2.2.4.int compareToIgnoreCase(String str) 方法:
与compareTo方式相同,但是忽略大小写比较。
public static void main(String[] args) {
String s2="Admin";
String s3="admin";
int ret1=s2.compareToIgnoreCase(s3);
System.out.println(ret1);
}
2.3.字符串的查找
字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法
有这么多的方法,具体大家自己去实践,在这只提供参考代码:
public static void main(String[] args) {
String s="aabcabcddcba";
//chatAt(i)返回i下标的字符
for (int i=0;i<s.length();i++){
System.out.print(s.charAt(i)+" ");
}
//indexof()
int ret=s.indexOf('b');
int ret1=s.indexOf("bc");
int ret2=s.indexOf("b",4);
int ret3=s.indexOf("dd",3);
//lastIndexOf()从后往前找
int ret4=s.lastIndexOf("d");
int ret5=s.lastIndexOf('b');
int ret6=s.lastIndexOf("cd",3);
int ret7=s.lastIndexOf('c',4);
System.out.println("======");
System.out.print(ret+" ");
System.out.print(ret1+" ");
System.out.print(ret2+" ");
System.out.print(ret3+" ");
System.out.print(ret4+" ");
System.out.print(ret5+" ");
System.out.print(ret6+" ");
System.out.print(ret7+" ");
}
2.4.字符串的转化
2.4.1.数值和字符串之间转化
数值转化为字符串
public static void main(String[] args) {
int a=10;
double b=20.6;
boolean flg=true;
String s1=String.valueOf(a);
String s2=String.valueOf(b);
String s3=String.valueOf(flg);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
字符串转化为数值
public static void main(String[] args) {
String s1="10";
String s2="20.4";
String s3="false";
int a=Integer.valueOf(s1);
double b= Double.valueOf(s2);
boolean c=Boolean.valueOf(s3);
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
2.4.2.大小写转化
toLowerCase();大写转化为小写
toUpperCase();小写转化为大写
public static void main(String[] args) {
String s1="HEllo";
s1=s1.toLowerCase();
System.out.println(s1);
System.out.println("=========");` String s1=String.format("%d-%d-%d",2000,1,1);
System.out.println(s1);
String s2="hEllO";
s2=s2.toUpperCase();
System.out.println(s2);
}
2.4.3.字符串转化为字符数组
public static void main(String[] args) {
String s="Hello world";
char[]chars=s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.print(chars[i]+" ");
}
}
2.4.4.格式化
String s1=String.format("%d-%d-%d",2000,1,1);
System.out.println(s1);
2.5.字符串的替换
String replaceAll(String regex, String replacement) 替换所有内容
String replaceFirst(String regex, String replacement) 替换首个内容
public static void main(String[] args) {
String s1="ababcabdeaf";
String ret1=s1.replaceFirst("a","b");
System.out.println(ret1);
System.out.println("======");
String ret2=s1.replace('a','o');
System.out.println(ret2);
}
2.6 字符串拆分
可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:
String[] split(String regex) 将字符串全部拆分
String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
public static void main(String[] args) {
String s1="hello world";
String[]strings=s1.split(" ");
for (String s:strings){
System.out.println(s);
}
}
public static void main(String[] args) {
String s1="hello world hello world";
String[]strings=s1.split(" ",2);
for(String s:strings){
System.out.println(s);
}
}
拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义.
代码示例: 拆分IP地址
public static void main(String[] args) {
String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;
for(String s: result) {
System.out.println(s);
}
}
注意事项:
- 字符"|“,”*“,”+"都得加上转义字符,前面加上 “\” .
- 而如果是 “” ,那么就得写成 “\\” .
- 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
代码示例: 多次拆分
public static void main(String[] args) {
String s="name=zhangsan&age=18";
String[]strings=s.split("&");
for(int i=0;i<strings.length;i++){
String[]strings1=strings[i].split("=");
for (int j=0;j< strings1.length;j++){
System.out.print(strings1[j]+" ");
}
System.out.println();
}
}
这样写比较麻烦,还有一种方式
public static void main(String[] args) {
String s="name=zhangsan&age=18";
String[]strings=s.split("&|=");
for (int i=0;i< strings.length;i++){
System.out.println(strings[i]);
}
}
2.7 字符串截取
从一个完整的字符串之中截取出部分内容。可用方法如下:
String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容
public static void main(String[] args) {
String s="abcabcde";
String s1=s.substring(0,3);
String s2=s.substring(3);
System.out.println(s1);
System.out.println("====");
System.out.println(s2);
}
注意事项:
- 索引从0开始
- 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
2.8.其他操作方法
String trim() 去掉字符串中的左右空格,保留中间空格
public static void main(String[] args) {
String s=" hel l o w orld ";
System.out.println(s);
String s1=s.trim();
System.out.println(s1);
}
2.9.字符串的不变性
大家会发现,许多方法我们在使用完的时候,我们要用一个字符串进行接受。这是因为String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:
1 . String类在设计时就是不可改变的,String类实现描述中已经说明了
String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:
- String类被final修饰,表明该类不能被继承
- value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中
的内容可以修改。
2 . 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象.
以replace为例
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。
public static void main(String[] args) {
final int array[] = {1,2,3,4,5};
array[0] = 100;
System.out.println(Arrays.toString(array));
array = new int[]{4,5,6};
}
会报错
已经初始化完了array数组,可以改变其中某个具体的值,但是就不能在进行初始化。
为什么 String 要设计成不可变的?(不可变对象的好处是什么?) (选学)
- 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
- 不可变对象是线程安全的.
- 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
那如果想要修改字符串中内容,该如何操作呢?
2.10 字符串修改
注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下
public static void main(String[] args) {
String s="hello";
s+=" world";
System.out.println(s);
}
其反汇编代码
其实等价于
public static void main(String[] args) {
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("hello");
stringBuilder.append(" world");
String s=stringBuilder.toString();
System.out.println(s);
}
通过下面的代码观察+法,和append方法的效率
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for(int i = 0; i < 10000; ++i){
s += i;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for(int i = 0; i < 10000; ++i){
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for(int i = 0; i < 10000; ++i){
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
}
可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder。
3. StringBuilder和StringBuffer
3.1 StringBuilder的介绍
由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大
部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅StringBuilder在线文档
这么多方法,大家以后要是有不会的,在进行使用吧。
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("hello");
StringBuilder sb2 = sb1;
// 追加:即尾插-->字符、字符串、整形数字
sb1.append(' '); // hello
sb1.append("world"); // hello world
sb1.append(123); // hello world123
System.out.println(sb1); // hello world123
System.out.println(sb1 == sb2); // true
System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h
System.out.println(sb1.length()); // 获取字符串的有效长度14
System.out.println(sb1.capacity()); // 获取底层数组的总大小
sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123
sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123
System.out.println(sb1);
System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置
System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置
sb1.deleteCharAt(0); // 删除首字符
sb1.delete(0,5); // 删除[0, 5)范围内的字符
String str = sb1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
System.out.println(str);
sb1.reverse(); // 字符串逆转
str = sb1.toString(); // 将StringBuffer以String的方式返回
System.out.println(str);
}
从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。
注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。
3.2 面试题:
String、StringBuffer、StringBuilder的区别
String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
StringBuffer与StringBuilder大部分功能是相似的
StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作。
4.String OJ题
1.第一个只出现一次的字符
2. 最后一个单词的长度
3.检测字符串是否为回文
完