一、字符串相关的类
String类
- 注意:误以为String是引用数据类型,实则String是一个特殊的类
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
1.String特性
String:字符串,使用一对""引起来表示。
- 1.String声明为final的,不可被继承
- 2.String
- 实现了Serializable接口:表示字符串是支持序列化的。
- 实现了Comparable接口:表示String可以比较大小
- 3.String内部定义了final char[] value用于存储字符串数据
- 4.String:代表不可变的字符序列。简称:不可变性。
体现:- 1.当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值。
- 2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
- 3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
- 5.通过字面量的方式(区别于其他类使用new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
- 6.字符串常量池中是不会存储相同内容的字符串的。
public class StringTest {
public void test1(){
String s1 = "abc";//字面量的定义方式
String s2 = "abc";
s1 = "hello";
System.out.println(s1 == s2);//true,说明s1和s2指向同一个地址值,比较s1和s2的地址值
System.out.println(s1);//hello
System.out.println(s2);//abc
System.out.println("*****************");
String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
System.out.println(s2);
System.out.println("*****************");
String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4);//abc
System.out.println(s5);//mbc
}
}
内存解析
2.String 对象的创建
1.
String str = "hello";
2.
//本质上this.value = new char[0];
String s1 = new String();
String str1 = “abc”;与String str2 = new String(“abc”);的区别?
(1)通过字面量定义的方式,此时数据声明在方法区中的字符串常量池中。
(2)通过new+构造器的方式:此时数据的地址值是数据在堆空间中开辟空间以后对应的地址值。
内存解析如下:
public class StringTest {
public void test2(){
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
System.out.println("***********************");
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true,两个name记录的都是常量池中Tom的地址值
p1.name = "Jerry";
System.out.println(p2.name);//Tom,不可变性,P1需在常量池中新造,故不影响p2
}
}
面试题:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?
两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:“abc”
注意:
(1) 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
(2)只要其中有一个是变量,结果就在堆中 。
(3)如果拼接的结果调用intern()方法,返回值就在常量池中
String s1="Hello";
String s2=s1+"World";
System.out.println(s1==s2);
此时结果是 false,但是
final String s1="Hello";
String s2=s1+"World";
System.out.println(s1==s2);
此时结果就是 true。
因为加了final,相当于s1变成了常量,常量的拼接在常量池中
3.String 的常用方法
常用方法1
- 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):比较两个字符串的大小
- S-tring substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
public class StringMethodTest {
public void test1() {
String s1 = "HelloWorld";
//int length():返回字符串的长度: return value.length
System.out.println(s1.length());//10
//char charAt(int index): 返回某索引处的字符return value[index]
System.out.println(s1.charAt(0));h
System.out.println(s1.charAt(9));l
//boolean isEmpty():判断是否是空字符串:return value.length == 0
System.out.println(s1.isEmpty());//false
//String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
//String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
String s2 = s1.toLowerCase();
System.out.println(s1);//HelloWorld,s1不可变的,仍然为原来的字符串
System.out.println(s2);//helloWorld改成小写以后的字符串
String s3 = " he llo world ";
//String trim():返回字符串的副本,忽略前导空白和尾部空白
String s4 = s3.trim();
System.out.println("-----" + s3 + "-----");
System.out.println("-----" + s4 + "-----");//-----he llo world-----
String s1 = "HelloWorld";
String s2 = "helloworld";
//boolean equals(Object obj):比较字符串的内容是否相同
//boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));
//String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
String s3 = "abc";
String s4 = s3.concat("def");
System.out.println(s4);
//int compareTo(String anotherString):比较两个字符串的大小
String s5 = "abc";
String s6 = new String("abe");
System.out.println(s5.compareTo(s6));//正数(s5>s6)负数(s5<s6),(a-b,b-b,c-e(99-101=-2))涉及到字符串排序
//String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
//String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。左闭右开
String s7 = "北京尚硅谷教育";
String s8 = s7.substring(2);
System.out.println(s7);
System.out.println(s8);
String s9 = s7.substring(2, 5);
System.out.println(s9);//尚硅谷
}
}
常用方法2
-
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个,如果超过了,剩下的全部都放到最后一个元素中。
public class StringMethodTest {
public void test3(){
String str1 = "hellowworld";
//boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
boolean b1 = str1.endsWith("rld");
System.out.println(b1);//true
//boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
boolean b2 = str1.startsWith("He");
System.out.println(b2);//fasle
//boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
boolean b3 = str1.startsWith("ll",2);
System.out.println(b3);//true
//boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
String str2 = "wor";
System.out.println(str1.contains(str2));//true
//int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
//int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
//int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
//int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
System.out.println(str1.indexOf("lol"));//-1(如果不存在就返回-1)
System.out.println(str1.indexOf("lo",5));
String str3 = "hellorworld";
System.out.println(str3.lastIndexOf("or"));//7
System.out.println(str3.lastIndexOf("or",6));//4
//什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?
//情况一:存在唯一的一个str。情况二:不存在str
String str1 = "北京尚硅谷教育北京";
//String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String str2 = str1.replace('北', '东');
System.out.println(str1);//北京尚硅谷教育北京
System.out.println(str2);//东京尚硅谷教育北京
//String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String str3 = str1.replace("北京", "上海");
System.out.println(str3);//上海尚硅谷教育上海
System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
//String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);
System.out.println("*************************");
str = "12345";
//boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);
//String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
System.out.println("*************************");
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
//String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
System.out.println();
str2 = "hello.world.java";
String[] strs2 = str2.split("\\.");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}
4.复习String类与其他结构之间的转换
String 与基本数据类型、包装类之间的转换。
- String --> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)
- 基本数据类型、包装类 --> String:调用String重载的valueOf(xxx)
public class StringTest1 {
public void test1(){
String str1 = "123";
// int num = (int)str1;//错误的
//String --> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)
int num = Integer.parseInt(str1);
//基本数据类型、包装类 --> String:调用String重载的valueOf(xxx)
String str2 = String.valueOf(num);//"123"
String str3 = num + "";
System.out.println(str1 == str3);
}
}
String 与 char[]之间的转换
- String --> char[]:调用String的toCharArray()
- char[] --> String:调用String的构造器
public class StringTest1 {
public void test2(){
String str1 = "abc123";
// String --> char[]:调用String的toCharArray()
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);
}
String 与 byte[]之间的转换
-
编码:String --> byte[]:调用String的getBytes()
-
解码:byte[] --> String:调用String的构造器
-
编码:字符串 -->字节 (看得懂 —>看不懂的二进制数据)
-
解码:编码的逆过程,字节 --> 字符串 (看不懂的二进制数据 —> 看得懂)
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
public class StringTest1 {
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行编码。
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码。
System.out.println(Arrays.toString(gbks));
System.out.println("******************");
String str2 = new String(bytes);//使用默认的字符集,进行解码。
System.out.println(str2);
String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因:编码集和解码集不一致!
String str4 = new String(gbks, "gbk");
System.out.println(str4);//没有出现乱码。原因:编码集和解码集一致!
}
5.面试:常见算法题目
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索引结束的左闭右开区间的子字符串
- public int length()
- public char charAt(int n )
- public void setCharAt(int n ,char ch)
总结:
- 增:append(xxx)
- 删:delete(int start,int end)
- 改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
- 查:charAt(int n )
- 插:insert(int offset, xxx)
- 长度:length();
- 遍历:for() + charAt() / toString()
StringBuilder类
三者异同
String、StringBuffer、StringBuilder三者的异同?
- String:不可变的字符序列;底层使用char[]存储
- StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
- StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
三者效率
对比String、StringBuffer、StringBuilder三者的效率:
从高到低排列:StringBuilder > StringBuffer > String
public class StringBufferBuilderTest {
/*
对比String、StringBuffer、StringBuilder三者的效率:
从高到低排列:StringBuilder > StringBuffer > String
*/
@Test
public void test3(){
//初始设置
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
二:JDK 8之前的日期时间API
1. java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。称为时间戳。
public class DateTimeTest {
//1.System类中的currentTimeMillis()
public void test1(){
long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
//称为时间戳
System.out.println(time);
}
}
2.java.util.Date类
表示特定的瞬间,精确到毫秒。
1.两个构造器的使用
- 构造器一:Date():创建一个对应当前时间的Date对象
- 构造器二:创建指定毫秒数的Date对象
2.两个方法的使用
- toString():显示当前的年、月、日、时、分、秒
- getTime():获取当前Date对象对应的毫秒数。(时间戳)
3.java.sql.Date对应着数据库中的日期类型的变量
- 如何实例化
- 如何将java.util.Date对象转换为java.sql.Date对象
public class DateTimeTest {
public void test2(){
//构造器一:Date():创建一个对应当前时间的Date对象
Date date1 = new Date();
System.out.println(date1.toString());//Sat Feb 16 16:35:31 GMT+08:00 2019
System.out.println(date1.getTime());//1550306204104
//构造器二:创建指定毫秒数的Date对象
Date date2 = new Date(155030620410L);
System.out.println(date2.toString());
//创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(35235325345L);
System.out.println(date3);//1971-02-13
//如何将java.util.Date对象转换为java.sql.Date对象
//情况一:
Date date4 = new java.sql.Date(2343243242323L);
java.sql.Date date5 = (java.sql.Date) date4;
//情况二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
}
3. java.text.SimpleDateFormat类
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
1.两个操作:
- 格式化:日期 —>字符串
- 解析:格式化的逆过程,字符串 —> 日期
2.SimpleDateFormat的实例化
默认输出指定格式:使用默认的构造器
public class DateTimeTest {
public void testSimpleDateFormat() throws ParseException {
//实例化SimpleDateFormat:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
//格式化:日期 --->字符串
Date date = new Date();
System.out.println(date);//Mon Feb 3 14:23:34 GMT+08:00 2019
String format = sdf.format(date);
System.out.println(format);//20-2-3 下午14:23
//解析:格式化的逆过程,字符串 ---> 日期
String str = "19-12-18 上午11:43";
Date date1 = sdf.parse(str);
System.out.println(date1);
}
按照指定的方式格式化和解析:调用带参的构造器
public class DateTimeTest {
public void testSimpleDateFormat() throws ParseException {
// SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1);//2019-02-18 11:48:27
//解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),
//否则,抛异常
Date date2 = sdf1.parse("2020-02-18 11:48:27");
System.out.println(date2);
}
4. java.util.Calendar(日历)类
public class DateTimeTest {
/*
Calendar日历类(抽象类)的使用
*/
public void testCalendar(){
//1.实例化
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance()常选用!!!
Calendar calendar = Calendar.getInstance();
// System.out.println(calendar.getClass());
//2.常用方法
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);//当前月份的第几天
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//当前年的第几天
//set()
//calendar可变性
calendar.set(Calendar.DAY_OF_MONTH,22);//把当前月份的第几天,修改成22天
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
//add()
calendar.add(Calendar.DAY_OF_MONTH,-3);//当前月份的第几天,最终结果-3
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
//getTime():日历类---> Date
Date date = calendar.getTime();
System.out.println(date);
//setTime():Date ---> 日历类
Date date1 = new Date();
calendar.setTime(date1);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
}
三:JDK8中新日期时间API
1.LocalDate、LocalTime、LocalDateTime
LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。
LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
LocalTime表示一个时间,而不是日期。
LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
//now():获取当前的日期、时间、日期+时间
LocaDate localdate=LocalDate.now();
LocalTime localtime=LocalTime.now();
LocalDateTime localDateTime=LocalDateTime.now();
//of():设定指定的年、月、日、时、分、秒,没有偏移量
LocalDateTime localDateTime1=LocalDateTime.of(2020,12,15,19,00,00);
System.out.println(localDateTime1);
此时输出结果就是2020-12-15 T19:00:00
//getXxx():获取指定值
System.out.println(localDateTime.getDayOfMonth());//获取当前时间是本月的第几天
System.out.println(localDateTime.getDayOfWeek());//获取当前时间是本周的第几天
//withDayOfXxx(): 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象
LocalDate localDate1=localDate.withDayOfMonth(22);//将当前时间改成本月的第22天
LocalDateTime localDateTime3=localDateTime.plusMonths(3);//将当前时间是本月的天数加3
LocalDateTime localDateTime4=localDateTime.minusDays(6);//将当前时间是本月的天数减6
2.瞬时:Instant
Instant:时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳。
常用方法:
- ① now():静态方法,返回默认UTC时区的Instant类的对象。
Instant instant=Instant.now();
输出的是本初子午时间(与北京时间相差8个小时)。
- ② atOffset(ZoneOffset offset) :结合即时的偏移来创建一个 OffsetDateTime。
OffsetDateTime offsetDateTime=instant.atOffset(ZoneOffset.ofHours(8));
此时输出的是北京时间。
- ③ toEpochMilli() :返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳。时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
long milli=instant.toEpochMilli();
- ④ ofEpochMilli(long epochMilli): 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象。
类似于Date类的getTime()
Instant instant1=Instant.toEpochMilli(15550475314878L);
输出结果是与1970-01-01 00:00:00距离15550475314878毫秒的时间。
3.格式化与解析日期或时间
java.time.format.DateTimeFormatter 类:格式化或解析日期、时间。类似于SimpleDateFormat
① 三种实例化方式:
//方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter=DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期→字符串
LocalDateTime localDateTime=LocalDateTime.now();
String str1=formatter.format(localDateTime);
//输出结果就是字符串形式的当前时间
//解析:字符串→日期
TemporaAccessor parse=formatter.parse("2020-12-15T19:00:00");
此时输出的是括号里对应的日期
//方式二:本地化相关的格式。如:① ofLocalizedDateTime()
//FormatStyle.LONG /FormatStyle.MEDIUM /FormatStyle.SHORT :适用于LocalDateTime,三者对应的格式不同
DateTimeFormatter formatter1=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
//格式化:日期→字符串
String str2=formatter1.format(localDateTime);
//输出就是SHORT对应的格式
//解析:字符串→日期
TemporaAccessor parse=formatter1.parse("2020-12-15T19:00:00");
//本地化相关的格式。如:② ofLocalizedDate()
//FormatStyle.FULL /FormatStyle.LONG /FormatStyle.MEDIUM /FormatStyle.SHORT :适用于LocalDateTime,对应的格式不同
DateTimeFormatter formatter2=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
//格式化:日期→字符串
String str3=formatter2.format(localDate.now());
//自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter3=DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化:日期→字符串
String str4=formatter3.format(localDateTime.now());//此时str4的格式就是括号里的样子。
//解析:字符串→日期
TemporaAccessor parse=formatter3.parse("2020-12-15 19:00:00");
四、Java比较器
在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
Java实现对象排序的方式有两种:
- 自然排序:java.lang.Comparable
- 定制排序:java.util.Comparator
1.自然排序
Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
comparable 接口的使用举例:
1.像String、包装类等实现了 Comparable接口,重写了compareTo(Object obj)方法,给出了比较两个对象大小的方法。
2.像String、包装类等重写compareTo(Object obj)方法后,进行了从小到大的排列。
3.重写compareTo(Object obj)的规则:
① 如果当前对象this大于形参对象obj,则返回正整数,
② 如果当前对象this小于形参对象obj,则返回负整数,
③ 如果当前对象this等于形参对象obj,则返回零。
举例:
public class CompareTest {
public void test1(){
String[] arr = new String[]{
"AA","CC","KK","MM","GG","JJ","DD"};
//
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[AA,CC,KK,DD,GG,JJ,MM]
}
4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
商品类:
/**
* 商品类
* @author shkstart
* @create 2019 下午 4:52
*/
public class Goods implements Comparable{
private String name;
private double price;
public Goods() {
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
@Override
public int compareTo(Object o) {
if(o instanceof Goods){
Goods goods = (Goods)o;
//方式一:
if(this.price > goods.price){
return 1;
}else if(this.price < goods.price){
return -1;
}else{
// return 0;
return -this.name.compareTo(goods.name);
}
//方式二:
// return Double.compare(this.price,goods.price);
}
// return 0;
throw new RuntimeException("传入的数据类型不一致!");
}
}
public class CompareTest {
public void test2(){
Goods[] arr = new Goods[5];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",43);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",65);
arr[4] = new Goods("microsoftMouse",43);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
2.定制排序
1.背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,
那么可以考虑使用 Comparator 的对象来排序
2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
如果方法返回正整数,则表示o1大于o2;
如果返回0,表示相等;
返回负整数,表示o1小于o2。
public class CompareTest {
public void test3(){
String[] arr = new String[]{
"AA","CC","KK","MM","GG","JJ","DD"};
Arrays.sort(arr,new Comparator(){
//按照字符串从大到小的顺序排列
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof String && o2 instanceof String){
String s1 = (String) o1;
String s2 = (String) o2;
return -s1.compareTo(s2);
}
// return 0;
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
}
public class CompareTest {
public void test4(){
Goods[] arr = new Goods[6];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",43);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",65);
arr[4] = new Goods("huaweiMouse",224);
arr[5] = new Goods("microsoftMouse",43);
Arrays.sort(arr, new Comparator() {
//指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Goods && o2 instanceof Goods){
Goods g1 = (Goods)o1;
Goods g2 = (Goods)o2;
if(g1.getName().equals(g2.getName())){
return -Double.compare(g1.getPrice(),g2.getPrice());
}else{
return g1.getName().compareTo(g2.getName());
}
}
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
}
3.说明:
Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < 的, 但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
4.Comparable接口与Comparator的使用的对比:
- Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
- Comparator接口属于临时性的比较。
五、System类
- (1)System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
- (2)由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。
- (3)成员变量: System类内部包含in、out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
- (4)成员方法:
- ① native long currentTimeMillis(): 该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
- ② void exit(int status): 该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
- ③ void gc(): 该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
- ④ String getProperty(String key): 该方法的作用是获得系统中属性名为key的属性对应 的值。系统中常见的属性名以及属性的作用如下表所示:
举例:
public class OtherClassTest {
public void test1() {
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}
六、Math类
java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。
- abs 绝对值
- acos,asin,atan,cos,sin,tan 三角函数
- sqrt 平方根
- pow(double a,doble b) a的b次幂
- log 自然对数
- exp e为底指数
- max(double a,double b)
- min(double a,double b)
- random() 返回0.0到1.0的随机数
- long round(double a) double型数据a转换为long型(四舍五入)
- toDegrees(double angrad) 弧度—>角度
-toRadians(double angdeg) 角度—>弧度
七、BigInteger与BigDecimal
1.BigInteger
(1)基本知识
- Integer类作为int的包装类,能存储的最大整型值为2^31-1, Long类也是有限的,最大为2^63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
- java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
- 构造器 : BigInteger(String val):根据字符串构建BigInteger对象。
(2) 常用方法
public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。
BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。
BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
2.BigDecimal
(1)基本知识
一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。 BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
(2) 构造器
public BigDecimal(double val)
public BigDecimal(String val)
(3)常用方法
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)