Java常用类笔记
【摘要】 一、前言这篇技术博客是我复习尚硅谷JavaSE教程做的笔记总结,方便大家的学习同时也方便自己。博客内容非复制粘贴,纯手写。如果对你有帮助,欢迎点赞评论收藏!二、String类1.理解String的不可变性String:字符串,使用""引起来表示String声明为final的,不能被继承String实现了Serializable接口:表示字符串是支持序列化的实现了Comparable接口:表示...
一、前言
这篇技术博客是我复习尚硅谷JavaSE教程做的笔记总结,方便大家的学习同时也方便自己。博客内容非复制粘贴,纯手写。如果对你有帮助,欢迎点赞评论收藏!
二、String类
1.理解String的不可变性
String:字符串,使用""引起来表示
- String声明为final的,不能被继承
- String实现了Serializable接口:表示字符串是支持序列化的
实现了Comparable接口:表示String可以比较大小 - String在内部定义了final char[] value用于存储字符串数据
- String:代表不可变的字符序列。简称:不可变性。(只要对字符串内容进行任何修改,都必须重新造!)
体现:
1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能在原有的value上进行赋值
3.当调用String的replace()修改指定字符或字符串时,也需要重新指定内存区域赋值
- 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
- 字符串常量池中是不会存储相同内容的字符串的。
图解如下:
附加:JVM中字符串常量池存放位置说明
JDK1.6:字符串常量池存储在方法区(永久区)
JDK1.7:字符串常量池存储在堆空间
JDK1.8:字符串常量池存储在方法区(元空间)
2.String不同实例化方式对比
String共有两种实例化的方式:
- 通过字面量定义的方式
- 通过new + 构造器方式
/**
* 面试题:String s = new String("abc");方式创建对象,在内存中创建了几个对象?
* 两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"
*/
public class StringTest {
@Test
public void test1(){
//此时的s1和s2数据声明在方法区中的字符串常量池中
String s1 = "abc";
String s2 = "abc";
//new + 构造器方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间后对应的地址值
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s1 == s2); //true 因为字符串常量存储在方法区的常量池中,是唯一的(共享)
System.out.println(s1 == s3); //false s1指向常量池中的地址,s3指向堆空间地址
System.out.println(s1 == s4); //false s1指向常量池中的地址,s4指向对空间地址
System.out.println(s3 == s4); //false s3和s4都指向堆空间地址,但是地址值不同
}
}
总结:字符串分两种实例化方式,通过字面量实例化就存储在方法区的常量池中,通过new方式就存储在堆空间中。常量池中的常量是唯一且不可修改的,如果想使用新的常量,只能在池中创建新的!
3.String不同拼接操作的对比
结论:
- 1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
- 2.只要其中有一个是变量,结果就在堆中
- 3.如果拼接的结果调用intern()方法,返回值就在常量池中
public class StringTest {
@Test
public void test1(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); //true 常量和常量拼接,地址依旧在常量池,所以指向同一个地址
System.out.println(s3 == s5); //false 常量和变量拼接,地址就在堆空间中,所以没指向同一个地址
System.out.println(s3 == s6); //false 同理
System.out.println(s5 == s6); //false 同理
System.out.println(s3 == s7); //false 同理
System.out.println(s5 == s7); //false 同理
System.out.println(s6 == s7); //false 同理
String s8 = s5.intern(); //返回值得到的s8使用的常量池中已经存在的"JavaEEhadoop"
System.out.println(s3 == s8); //true
}
@Test
public void test1(){
String s1 = "javaEEhadoop";
String s2 = "javaEE";
String s3 = s2 + "hadoop";
System.out.println(s1 == s3); //false
final String s4 = "javaEE"; //s4是常量
String s5 = s4 + "hadoop";
System.out.println(s1 == s5); //true 原因:看结论1
}
}
4.String常用方法
- int length():返回字符串的长度: return value.length
- char charAt(int index): 返回某索引处的字符return value[index]
- boolean isEmpty():判断是否是空字符串:return value.length == 0
- String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
- String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
- String trim():返回字符串的副本,忽略前导空白和尾部空白
- boolean equals(Object obj):比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
- String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
- int compareTo(String anotherString):比较两个字符串的大小
- String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
- boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
- boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
- int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
- int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
- int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
- int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
注:indexOf和lastIndexOf方法如果未找到都是返回-1 - String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
- String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
代码演示:
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
//length()
String s1 = "HelloWorld";
System.out.println(s1.length()); //10
//charAt()
System.out.println(s1.charAt(0)); //H
System.out.println(s1.charAt(9)); //d
//isEmpty()
System.out.println(s1.isEmpty()); //false
//toLowerCase()
String s2 = s1.toLowerCase();
System.out.println(s2); //helloworld
//toUpperCase()
String s3 = s1.toUpperCase();
System.out.println(s3); //HELLOWORLD
//trim()
String s4 = " hello world ";
String s5 = s4.trim();
System.out.println("---" + s4 + "---"); //--- hello world ---
System.out.println("---" + s5 + "---"); //---hello world---
}
@Test
public void test2(){
//equalsIgnoreCase()
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2)); //false
System.out.println(s1.equalsIgnoreCase(s2)); //true
//concat()
String s3 = "abc";
String s4 = s3.concat("def");
System.out.println(s4); //abcdef
//compareTo()
String s5 = "abc";
String s6 = new String("abe");
System.out.println(s5.compareTo(s6)); //涉及到字符串排序
//substring()
String s7 = "北京天安门广场";
System.out.println(s7.substring(2)); //天安门广场
//endIndex()
System.out.println(s7.substring(2, 5)); //天安门
}
@Test
public void test3(){
//endsWith()
String str1 = "helloworld";
boolean b1 = str1.endsWith("ld");
System.out.println(b1); //true
//startsWith()
boolean b2 = str1.startsWith("He");
System.out.println(b2); //false
boolean b3 = str1.startsWith("ll",2);
System.out.println(b3); //true
//contains()
String str2 = "wo";
System.out.println(str1.contains(str2)); //true
//indexOf()
System.out.println(str1.indexOf("lo")); //3
System.out.println(str1.indexOf("lol")); //-1
System.out.println(str1.indexOf("lo",5)); //-1
//lastIndexOf()
String str3 = "hellorworld";
System.out.println(str3.lastIndexOf("or")); //7
System.out.println(str3.lastIndexOf("or",6)); //4
//什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?
//1.存在唯一的的一个str 2.不存在str
}
@Test
public void test4(){
//replace()
String str1 = "北京尚硅谷教育北京";
String str2 = str1.replace('北', '东');
String str3 = str1.replace("北京", "上海");
System.out.println(str1); //北京尚硅谷教育北京
System.out.println(str2); //东京尚硅谷教育东京
System.out.println(str3); //上海尚硅谷教育上海
}
}
5.String类与其他结构之间的转换
/**
* 涉及到String类与其他结构之间的转换
*/
public class StringTest {
@Test
public void test1(){
//String--->基本数据类型、包装类
String str1 = "123";
int num = Integer.parseInt(str1); //123
//基本数据类型、包装类--->String
String str2 = String.valueOf(num); //"123"
String str3 = num + "";
}
@Test
public void test2(){
/*
String与char[]之间的转换
*/
//String--->char[]:调用String的toCharArray()
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.println(charArray[i]);
}
//char[]--->String:调用String的构造器
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2); //hello
}
@Test
public void test3() throws UnsupportedEncodingException {
/*
String与byte[]之间转换
编码:字符串--->字节(看得懂--->看不懂)
解码:编码的逆过程,字节--->字符串(看不懂的二进制数据--->看得懂)
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码
*/
//编码:String--->byte[]:调用
String str1 = "abc123中国";
byte[] bytes = str1.getBytes(); //使用默认的字符集(utf-8)进行编码
//[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67]
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk"); //使用gbk字符集进行编码
//[97, 98, 99, 49, 50, 51, -42, -48, -71, -6]
System.out.println(Arrays.toString(gbks));
//解码:byte[]--->String:调用String构造器
String str2 = new String(bytes); //使用默认的字符集,进行解码
System.out.println(str2); //abc123中国
String str3 = new String(gbks);
System.out.println(str3); //出现乱码,原因:编码集和解码集不一致!
String str4 = new String(gbks, "gbk");
System.out.println(str4); //没有出现乱码,原因:编码集和解码集一致!
}
}
三、StringBuffer类和StringBuilder类
1.StringBuffer分析(StringBuilder同理)
StringBuffer类不同于String,其对象必须使用构造器生成。
- StringBuffer():初始容量为16的字符串缓冲区
- StringBuffer(int size):构造指定容量的字符串缓冲区
- StringBuffer(String capacity):将内容初始化为指定字符串内容
String、StringBuffer、StringBuilder三者异同?
String:不可变的字符序列;底层结构使用char[]存储
StringBuffer:可变的字符序列,线程安全的,效率低;底层结构使用char[]存储
StringBuilder:可变的字符序列,jdk5.0新增,线程不安全的,效率高;底层结构使用char[]存储
String str = new String(); //char[] value = new char[0];
String str1 = new String("abc"); //char[] value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer(); //char[] value = new char[16]; 底层创建了一个长度是16的数组
sb1.append('a'); //value[0] = 'a';
sb1.append('b'); //value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc"); //char[] value = new char["abc".length() + 16];
问题1:System.out.println(sb2.length()); //3
问题2:扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层数组
默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中
指导意义:在开发中,建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)
注意:String、StringBuffer、StringBuilder三者之间如何转换?
String-->StringBuffer、StringBuilder:
1.调用StringBuffer、StringBuilder构造器
StringBuffer、StringBuilder-->String:
1.调用String构造器
2.StringBuffer、StringBuilder的toString()
理解:关于StringBuffer和StringBuilder这两个类,它们之间除了类名不同,唯一的区别就是:是否同步(synchronized)
2.StringBuffer常用方法(StringBuilder同理)
String类中定了许多方法,StringBuffer中也有。但是StringBuffer还有一些独有的方法,我们来了解了解:
- StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
- StringBuffer delete(int start,int end):删除指定位置的内容
- StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
- StringBuffer insert(int offset, xxx):在指定位置插入xxx
- StringBuffer reverse() :把当前字符序列逆转
- public int indexOf(String str)
- public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串1
- public int length()
- public char charAt(int n)
- public void setCharAt(int n ,char ch)
代码展示:
public class StringTest {
@Test
public void test2(){
//append()
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);
s1.append('1');
System.out.println(s1); //abc11
//delete()
//s1.delete(2,4); //ab1
//replace()
//s1.replace(2,4,"hello"); //abhello1
//insert()
//s1.insert(2,false); //abfalsec11
//reverse()
//s1.reverse(); //11cba
//sustring()
//String s2 = s1.substring(1, 3); //bc
}
}
总结:
增:append(xxx)
删:delete(int start,int end)
改:setCharAt(int n ,char ch)
查:charAt(int n)
插:insert(int offset, xxx)
长度:length()
遍历:for() + charAt(int n) / toString()
3.效率对比
接下来我们探讨一下:String、StringBuffer、StringBuilder三者之间的效率对比
代码展示:
public class StringTest {
@Test
public void test2(){
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//开始对比
//StringBuffer时间
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
//StringBuilder测试时间
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
//String测试时间
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
运行结果如下:
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)