目录
4.String,StringBuffer,StringBuilder对比
1.String概述
java中所有用" "双引号括起来的都是String类的对象,String类的对象有以下特征
1.1 字符串的不变性
字符串对象一旦创建就不能改变
public class String2 {
public static void main(String[] args) {
//字符串不变,它们的值在创建后不能被更改
String s = "abcd";//abcd 第一个字符串对象
s += "efg";//abcdefg 第二个字符串对象
s += "aaaa";//abcdefgaaaa 第三个字符串对象
System.out.println(s);
}
}
上述代码,看似是s一直+=字符串,s好像是变了,但其实这是三个不同的字符串对象,只是s的指向一直在改变,所以当+=字符串次数很多时,是相当占用资源的
1.2 创建String对象两种方式的区别
方式一:
public class String1 {
/*
java.lang.String
java中所有字符串都是此类的实例
"abc" -->字符串对象 底层是一个char数组 private final char value['a','b','c'];
字符串对象创建方式:
1.String s = "abc"
创建时会先去字符串常量池中查找有没有值相同的对象,如果没有,就创建一个字符串对象,并返回地址
如果字符串常量池中有,不用创建新的,直接返回已存在的对象的地址
*/
public static void main(String[] args) {
String s = "abc";
String ss = "abc";
System.out.println(s == ss);//true
System.out.println(s.equals(ss));//true
}
}
直接用一个字符串常量赋值给String类的对象,eg:String s ="abc";
用这种方式创建一个字符串对象,编译器会先在字符串常量池中找有没有与其值相同的字符串,如果有,则直接将该引用指向字符串常量池中的字符串,如果没有会在字符串常量池中创建一个该字符串,并将引用指向该对象,所以用这种方式创建两个值相同的字符串时用 == 判断返回的是true,因为它们指向字符串常量池中的同一个字符串
方式二:
public class String1 {
/*
2.String s1 = new String("abc");
new 每次都是在堆中创建新的字符串对象
*/
public static void main(String[] args) {
String s = "abc";
String ss = "abc";
System.out.println(s == ss);//true
System.out.println(s.equals(ss));//true
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2));//true
}
}
用new调用构造方法创建对象,这种方式在创建时地址肯定是不一样的,new创建对象就是在堆中开辟不同的空间,然后将字符串填充进去,用==判断两个值相同的字符串对象时返回的是false
1.3 字符串中的构造方法
(1)String()
无参构造
String s1 = new String();
(2)String(String s)
用一个字符串构造字符串对象
String s2 = new String("abc");
(3)String(byte[ ] bytes)
用一个字节数组构造字符串对象
String s3 = "你好";
byte[] bytes = s3.getBytes();//编码 把字符转为 字节数组(数字)
System.out.println(Arrays.toString(bytes));
String s4 = new String(bytes,"GBK");//解码 把字节数组转为字符
System.out.println(s4);
字符串中有一个getBytes()方法,可以将字符串转为字节数组,然后再利用String(byte[ ] bytes)将字节数组转为字符串可实现编码和解码
(4)String(char[ ] chars)
用一个字符数组构造字符串对象
String s5 = "cab";
char[] chars = s5.toCharArray();//把字符串转为字符数组
Arrays.sort(chars);
String s6 = new String(chars);//把字符数组转为字符串
System.out.println(s6);
字符串中有一个toCharArray()方法可以将字符串转为字符数组,可以配合String(char[ ] chars)使用
1.4 字符串判断功能的方法
public class String4 {
/*
判断功能
boolean equals(Object obj) //比较两个字符串的内容是否相等
boolean equalsIgnoreCase(String str)//判断两个字符串的内容是否相等,忽略大小写
boolean contains(String str)//判断字符串中是否包含指定的子串
boolean isEmpty()//判断字符串是否为空串""
boolean startsWith(String prefix)//判断是否以指定的字符串开头
boolean endsWith(String suffix)//判断是否以指定的字符串结尾
*/
public static void main(String[] args) {
String s1 = new String("abcd");
String s2 = new String("abcD");
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));
System.out.println(s1.contains("ac"));
System.out.println(s1.isEmpty());
System.out.println(s1.startsWith("ab"));
System.out.println(s1.endsWith("cd"));
}
}
判断功能
(1) boolean equals(Object obj) //比较两个字符串的内容是否相等
(2) boolean equalsIgnoreCase(String str)//判断两个字符串的内容是否相等,忽略大小写
(3) boolean contains(String str)//判断字符串中是否包含指定的子串
(4) boolean isEmpty()//判断字符串是否为空串""
(5) boolean startsWith(String prefix)//判断是否以指定的字符串开头
(6) boolean endsWith(String suffix)//判断是否以指定的字符串结尾
1.5 字符串获取功能的方法
public class String5 {
/*
获取功能
int length();//获取字符串长度
char charAt(int index);//获取指定位置上的字符
int indexOf(String str);返回指定字符串首次出现的位置
int indexOf(String str,int fromIndex);从指定的位置位置开始查找,返回指定字符串首次出现的位置
int lastIndex(String str);//从右向左查找,返回指定字符串首次出现的位置
String substring(int start);//从指定的开始位置开始截取一个字符串副本到完
String substring(int start,int end)从指定的开始位置截取一个字符串副本到指定位置(不包含结束位置)
*/
public static void main(String[] args) {
String s1 = "abcdefgcd";
//012345678
System.out.println(s1.length());
System.out.println(s1.charAt(4));
for (int i = 0; i < s1.length(); i++) {
System.out.print(s1.charAt(i));
}
System.out.println();
System.out.println(s1.indexOf("cd"));
System.out.println(s1.indexOf("c",3));
System.out.println(s1.lastIndexOf("c"));
System.out.println(s1.lastIndexOf("c",6));
String s2 = s1.substring(3);
String s3 = s1.substring(0,6);//左闭右开
System.out.println(s2);
System.out.println(s3);
}
}
获取功能
(1) int length();//获取字符串长度
(2) char charAt(int index);//获取指定位置上的字符
(3) int indexOf(String str);返回指定字符串首次出现的位置
(4) int indexOf(String str,int fromIndex);从指定的位置位置开始查找,返回指定字符串首次出现的位置
(5) int lastIndex(String str);//从右向左查找,返回指定字符串首次出现的位置
(6) String substring(int start);//从指定的开始位置开始截取一个字符串副本到完
(7) String substring(int start,int end)从指定的开始位置截取一个字符串副本到指定位置(不包含结束位置)
1.6 字符串转换功能的方法
public class String6 {
public static void main(String[] args) {
/*
转换功能
byte[] getBytes();将字符串转为字节数组
char[] toCharArray()将字符串转为字符数组
static String valueOf(char[] chs)将字符数组转为字符串
static String valueOf(int a)将传入的参数转为字符串类型
String toLowerCase()将英文字母转为小写
String toUpperCase()将英文字母转为大写
String concat(String str)拼接指定的字符串内容到原字符串末尾,返回一个新的字符串对象
Stirng[] split(分割符);将一个字符串用指定的分隔符拆分成一个字符串数组
*/
String s = String.valueOf(1234);
System.out.println(s.charAt(1));
int a = Integer.parseInt(s);
String s1 = String.valueOf("abc".toCharArray());
System.out.println(s1);
String s2 = "account=admin;account=123;account=456";
System.out.println(s2.toLowerCase());
System.out.println(s2.toUpperCase());
String s3 = s2.concat("aaa");
System.out.println(s3);
String[] strings = s2.split(";");
System.out.println(Arrays.toString(strings));
}
}
转换功能
(1) byte[] getBytes();将字符串转为字节数组
(2) char[] toCharArray()将字符串转为字符数组
(3) static String valueOf(char[] chs)将字符数组转为字符串
(4) static String valueOf(int a)将传入的参数转为字符串类型
(5) String toLowerCase()将英文字母转为小写
(6) String toUpperCase()将英文字母转为大写
(7) String concat(String str)拼接指定的字符串内容到原字符串末尾,返回一个新的字符串对象
(8) Stirng[] split(分割符);将一个字符串用指定的分隔符拆分成一个字符串数组
1.7 字符串替换功能的方法
public class String7 {
/*
替换功能
String replace(char old,char new)用新的字符替换字符串中指定的字符
String replace(String old,String new)用新的字符串替换字符串中指定的字符串
replaceAll(String regex, String replacement)用新内容替换字符串中正则表达式匹配的字符串
replaceFirst(String regex, String replacement)用新内容替换字符串中正则表达式匹配的字符串,只替换第一个
String trim()去除字符串两端的空格
*/
public static void main(String[] args) {
String s = " 2b3 cd 2efc5g ";
System.out.println(s.replace("2","C"));
System.out.println(s.replaceAll("\\d","C"));
System.out.println(s.replaceFirst("\\d","C"));
System.out.println(s.length());
System.out.println(s.trim().length());
}
}
替换功能
(1) String replace(char old,char new) 用新的字符替换字符串中指定的字符
(2) String replace(String old,String new) 用新的字符串替换字符串中指定的字符串
(3) replaceAll(String regex, String replacement) 用新内容替换字符串中正则表达式匹配的字符串
(4) replaceFirst(String regex, String replacement) 用新内容替换字符串中正则表达式匹配的字符串,只替换第一个
(5) String trim() 去除字符串两端的空格
注意:
这里要注意replace和replaceAll方法的区别,两个都可以对所有字符进行替换,不要被名字迷惑,replaceAll()方法的匹配方式可以传入一个正则表达式,而replace()方法传入的是用谁替换谁是字符串
2.StringBuffer
因为String类的对象一旦创建就不能改变,并且在进行字符串的拼接时,要频繁创建新的对象,既占用空间,又耗时,所以有了StringBuffer类,StringBuffer类的对象底层的数组没有被final修饰,所以在操作时,可以直接在原来的字符串上改变,不用创建新的字符串对象
2.1 构造方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();//空的构造方法指定底层数组长度是16
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
StringBuffer s3 = new StringBuffer(10);//还可以指定底层数组长度
}
}
(1) StringBuffer()
空的构造函数,底层会产生一个默认长度为16的char数组
(2) StringBuffer(String str)
用一个字符串初始化StringBuffer,底层会产生一个字符串长度+16的char数组
(3) StringBuffer(int capacity)
也可以用该构造方法指定底层数组的长度
2.2 插入方法
2.2.1 append()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s1.append("abcd");//向字符串末尾添加内容
System.out.println(s1);
s1.append("efg");
System.out.println(s1);
s1.append("hijk");
System.out.println(s1);
s1.append("aaaa");
System.out.println(s1);
}
该方法是直接在原字符串末尾进行追加,每追加一次就会判断当前长度是否大于数组长度,如果大于就会new一个新的字符数组,长度是2 * length(元数组长度) + 2个,并将原来数组中的值拷贝到新数组中,在改变原来数组的引用
2.2.2 Insert()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s2.insert(1,"A");//向指定的位置上插入指定的字符串
System.out.println(s2);
}
}
Insert()方法就是在指定位置处插入一个字符或字符串
2.3 删除方法
2.3.1 deleteCharAt()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s1.deleteCharAt(1);//删除指定位置上的字符
System.out.println(s2);
}
该方法是删除指定位置处的字符
2.3.2 delete()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s2.delete(0,3);//删除指定区间的元素,左闭右开
System.out.println(s2);
}
}
删除指定区间的字符串,左闭右开
2.4 其他方法
2.4.1 replace()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s2.replace(0,4,"AAA");
System.out.println(s2);
}
}
该方法使用一个字符串替换指定区间内的字符串
2.4.2 reverse()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
s2.reverse();//反转字符串
System.out.println(s2);
}
}
该方法可以反转一个字符串
2.4.3 substring()方法
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer s2 = new StringBuffer("abcd");//有参构造,底层数组长度为字符串长度+16
String s2 = s1.substring(0,5);//截取字符串,从StringBuffer中截取一个字符串副本,返回给一个新的String对象,StringBuffer对象不变
System.out.println(s2);
}
}
该方法是截取指定区间(左闭右开)的字符串,原字符串不变,是拷贝了一份进行截取
3.StringBuilder
StringBuilder和StringBuffer基本相同,都是继承了AbstractStringBuilder,相当于向外提供了两个类,但实际上调用的是都是AbstractStringBuilder中的方法,唯一的区别就是StringBuffer的方法中加了synchronized关键字,是线程安全的,而StringBuilder是线程不安全的
4.String,StringBuffer,StringBuilder对比
String:是一个值不可以改变的字符串
StringBuffer:值可以改变且不需要创建新对象, 方法上都加了锁, 是在多线程(任务)执行时是线程安全的
StringBuilder: 值可以改变且不需要创建新对象, 由于方法上都没有加锁,在多线程(任务)执行时是线程不安全的, 适合单线程