String:字符串,使用一对""引起来表示。
1.String声明为final的,不可被继承。
2.String实现了Serializable接口:表示字符串是支持序列化的;实现了Comparable接口:表示String可以比较大小。
3.String内部定义了final char[ ] value 用于存储字符串数据。
4.String:代表不可变的字符序列。简称:不可变性。
体现"不可变性":
(1)当对字符串重新赋值时,需要重新指定内存区域并赋值,不能使用原有的value进行赋值。(因为value是“final”的)
(2)当对现有的字符串进行连接操作时,也需要重新指定内存区域并赋值,不能使用原有的value进行赋值。
(3)当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域并赋值,不能使用原有的value进行赋值。
5.通过字面量的方式给一个字符串赋值,此时的字符串值声明在字符串常量池当中。
6.字符串常量池中是不会存储相同内容的字符串的。
package com.java.string; import org.junit.Test; /** * @description: * String的使用 * @author: Fish_Vast * @Date: 2021/9/14 * @version: 1.0 */ public class StringTest { @Test public void test1(){ String s1 = "abc"; //字面量的定义方式 String s2 = "abc"; s1 = "hello"; System.out.println(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("**********"); String s4 = "abc"; String s5 = s4.replace("abc","def"); System.out.println(s4); //abc System.out.println(s5); //def } }
(1)方式一:通过字面量定义的方式
(2)方式二:通过 new + 构造器 的方式
答:两个。(1)堆空间中new结构,(2)char[ ]对应的常量池中的数据:"abc"
package com.java.string; import org.junit.Test; /** * @description: * String的实例化 * @author: Fish_Vast * @Date: 2021/9/14 * @version: 1.0 */ public class StringTest2 { @Test public void show(){ //方式一:通过字面量定义的方式 //此时的s1和s2的数据abc声明在方法区中的字符串常量池中 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 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 字面量定义的方式,指向的是同一个地址值(都在常量池中)。 } }
结论:
●常量与常量的拼接结果在常量池。 且常量池中不会存在相同内容的常量。
●只要其中有一个是变量, 结果就在堆中。
●如果拼接的结果调用intern()方法, 返回值就在常量池中。
package com.java.string; import org.junit.Test; /** * @description: * 结论 * @author: Fish_Vast * @Date: 2021/9/18 * @version: 1.0 */ public class StringTest3 { @Test public void test(){ String s1 = "JavaHadoop"; String s2 = "Java"; String s3 = s2 + "Hadoop"; System.out.println(s1 == s3); //false final String s4 = "Java"; //s4通过final修饰,成为了一个常量 String s5 = s4 + "Hadoop"; System.out.println(s1 == s5); //true } @Test public void show(){ String s1 = "abc"; String s2 = "def"; String s3 = "abcdef"; String s4 = "abc" + "def"; String s5 = s1 + "def"; String s6 = "abc" + s2; String s7 = s1 + s2; String s8 = s5.intern(); System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false System.out.println(s3 == s6);//false System.out.println(s3 == s7);//false System.out.println(s3 == s8);//true } }
package com.java.string; import org.junit.Test; import java.io.UnsupportedEncodingException; import java.util.Arrays; /** * @description: * 1.String 与基本数据类型、包装类之间的转换 * String --> 基本数据类型、包装类: 调用包装类的静态方法:parseXxx(str) * 基本数据类型、包装类 --> String: 调用String重载的valueOf(xxx) * * 2.String 与 char[] 之间的转换 * String --> char[]:调用String的toCharArray() * char[] --> String:调用String的构造器 * * 3.String 与 byte[] 之间的转换 * 编码: String --> byte[]:调用String的getBytes() * 解码: byte[] --> String:调用String的构造器 * 编码: 字符串-->字节(看得懂 --> 看不懂的二进制数据) * 解码: 编码的逆过程,字节-->字符串(看不懂的二进制数据 --> 看得懂) * 说明:解码时,要求解码使用的字符集需要与编码时使用的字符集一致,否则会出现乱码。 * @author: Fish_Vast * @Date: 2021/9/22 * @version: 1.0 */ public class StringTest5 { @Test //String 与 byte[] 之间的转换 public void test2() throws UnsupportedEncodingException { String s1 = "abc中国"; byte[] bytes = s1.getBytes();//使用默认的字符集,进行编码 System.out.println(Arrays.toString(bytes)); byte[] gbks = s1.getBytes("gbk");//使用GBK字符集(大小写都可以),进行编码 System.out.println(Arrays.toString(gbks)); String s2 = new String(bytes);//使用默认的字符集,进行解码 System.out.println(s2); String s3 = new String(gbks); System.out.println(s3);//出现乱码,原因:编码集和解码集不一致 String s4 = new String(gbks,"gbk"); System.out.println(s4);//未乱码,原因:编码集和解码集一致 } @Test //String 与 char[] 之间的转换 public void test1(){ String s1 = "abc123"; char[] charArray = s1.toCharArray(); for (int i = 0; i < charArray.length; i++) { System.out.println(charArray[i]); } char[] arr = new char[]{'h','e','l','l','o'}; String s2 = new String(arr); System.out.println(s2); } @Test //String 与基本数据类型、包装类之间的转换 public void test(){ String s1 = "123"; // int num = (int)s1;//错误的 int num = Integer.parseInt(s1); System.out.println(num); System.out.println(String.valueOf(num)); } }
● 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个, 如果超过了, 剩下的全部都放到最后一个元素中。
package com.java.string; import org.junit.Test; /** * @description: *String类中的常用方法 * @author: Fish_Vast * @Date: 2021/9/22 * @version: 1.0 */ public class StringMethodTest { @Test public void test4(){ //替换 String s1 = "好浩浩哟"; System.out.println(s1); System.out.println(s1.replace('哟', '呀')); //单引号 System.out.println(s1.replace("浩", "娃")); //双引号 String s2 = "123java456mysql789spring101112mybatis"; //把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉 System.out.println(s2.replaceAll("\\d+", ",").replaceAll("^,|,$", "")); System.out.println(s2.replaceFirst("\\d+", ",").replaceFirst("^,|,$", "")); //匹配 String s3 = "12345"; System.out.println(s3.matches("\\d+")); String tel = "0517-1568990"; System.out.println(tel.matches("0517-\\d{7,8}")); //切片 String s4 = "hello|world|java"; String[] str = s4.split("\\|"); for (int i = 0; i < str.length; i++) { System.out.println(str[i]); } String s5 = "hello.world.java"; String[] str2 = s5.split("\\."); for (int i = 0; i < str2.length; i++) { System.out.println(str2[i]); } } @Test //在什么情况下,indexOf(str)和lastIndexOf(str)的返回值相同? //(1)存在唯一的一个str;(2)不存在str。 public void test3(){ String s1 = "HelloWorld"; System.out.println(s1.endsWith("ld")); System.out.println(s1.startsWith("Hel")); System.out.println(s1.startsWith("llo", 2)); String s2 = "Wor"; System.out.println(s1.contains(s2)); System.out.println(s1.indexOf("o")); System.out.println(s1.indexOf("l", 3)); System.out.println(s1.lastIndexOf("o")); System.out.println(s1.lastIndexOf("o", 5)); } @Test public void test2(){ String s1 = "HelloWorld"; String s2 = "helloworld"; //切换大小写快捷键ctrl+shift+U System.out.println(s1.equals(s2)); System.out.println(s1.equalsIgnoreCase(s2)); String s3 = "abc"; String s4 = s3.concat("def"); System.out.println(s3); System.out.println(s4); String s5 = "abc"; String s6 = "abe"; System.out.println(s5.compareTo(s6));//涉及到字符串的排序(例如:手机通讯录) String s7 = "浩浩好好哟!"; System.out.println(s7.substring(2)); System.out.println(s7.substring(0,3));//从哪开始到哪结束,一般都是“左闭区间右开区间”。 } @Test public void test1(){ String s1 = "HelloWorld"; System.out.println(s1.length()); System.out.println(s1.charAt(0)); System.out.println(s1.charAt(9)); System.out.println(s1.isEmpty()); String s2 = s1.toLowerCase(); String s3 = s1.toUpperCase(); System.out.println(s1); //s1不可变,仍然为原来的字符串 System.out.println(s2); //改写小写以后的字符串 System.out.println(s3); //改写大写以后的字符串 String s4 = " He llo Wor ld "; String s5 = s4.trim(); System.out.println(s4); System.out.println(s5); } }
1. 模拟一个trim方法,去除字符串两端的空格。
2. 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”。
3. 获取一个字符串在另一个字符串中出现的次数。比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数。
4. 获取两个字符串中最大相同子串。比如:str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”。提示:将短的那个串进行长度依次递减的子串与较长的串比较。
5. 对字符串中字符进行自然顺序排序。提示:
–>1) 字符串变成字符数组。
–>2) 对数组排序,选择,冒泡, Arrays.sort();
–>3) 将排序后的数组变成字符串。
package com.java.string; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; /** * @description: * String类的常见算法 * @author: Fish_Vast * @Date: 2021/9/22 * @version: 1.0 */ public class StringExer { // 第1题 public String myTrim(String str) { if (str != null) { int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引 int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引 while (start < end && str.charAt(start) == ' ') { start++; } while (start < end && str.charAt(end) == ' ') { end--; } if (str.charAt(start) == ' ') { return ""; } return str.substring(start, end + 1); } return null; } // 第2题 // 方式一: public String reverse1(String str, int start, int end) {// start:2,end:5 if (str != null) { // 1. char[] charArray = str.toCharArray(); // 2. for (int i = start, j = end; i < j; i++, j--) { char temp = charArray[i]; charArray[i] = charArray[j]; charArray[j] = temp; } // 3. return new String(charArray); } return null; } // 方式二: public String reverse2(String str, int start, int end) { // 1. String newStr = str.substring(0, start);// ab // 2. for (int i = end; i >= start; i--) { newStr += str.charAt(i); } // abfedc // 3. newStr += str.substring(end + 1); return newStr; } // 方式三:推荐 (相较于方式二做的改进) public String reverse3(String str, int start, int end) {// ArrayList list = new ArrayList(80); // 1. StringBuffer s = new StringBuffer(str.length()); // 2. s.append(str.substring(0, start));// ab // 3. for (int i = end; i >= start; i--) { s.append(str.charAt(i)); } // 4. s.append(str.substring(end + 1)); // 5. return s.toString(); } @Test public void testReverse() { String str = "abcdefg"; String str1 = reverse3(str, 2, 5); System.out.println(str1);// abfedcg } // 第3题 // 判断str2在str1中出现的次数 public int getCount(String mainStr, String subStr) { if (mainStr.length() >= subStr.length()) { int count = 0; int index = 0; // while((index = mainStr.indexOf(subStr)) != -1){ // count++; // mainStr = mainStr.substring(index + subStr.length()); // } // 改进: while ((index = mainStr.indexOf(subStr, index)) != -1) { index += subStr.length(); count++; } return count; } else { return 0; } } @Test public void testGetCount() { String str1 = "cdabkkcadkabkebfkabkskab"; String str2 = "ab"; int count = getCount(str1, str2); System.out.println(count); } @Test public void testMyTrim() { String str = " a "; // str = " "; String newStr = myTrim(str); System.out.println("---" + newStr + "---"); } // 第4题 // 如果只存在一个最大长度的相同子串 public String getMaxSameSubString(String str1, String str2) { if (str1 != null && str2 != null) { String maxStr = (str1.length() > str2.length()) ? str1 : str2; String minStr = (str1.length() > str2.length()) ? str2 : str1; int len = minStr.length(); for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符 for (int x = 0, y = len - i; y <= len; x++, y++) { if (maxStr.contains(minStr.substring(x, y))) { return minStr.substring(x, y); } } } } return null; } // 如果存在多个长度相同的最大相同子串 // 此时先返回String[],后面可以用集合中的ArrayList替换,较方便 public String[] getMaxSameSubString1(String str1, String str2) { if (str1 != null && str2 != null) { StringBuffer sBuffer = new StringBuffer(); String maxString = (str1.length() > str2.length()) ? str1 : str2; String minString = (str1.length() > str2.length()) ? str2 : str1; int len = minString.length(); for (int i = 0; i < len; i++) { for (int x = 0, y = len - i; y <= len; x++, y++) { String subString = minString.substring(x, y); if (maxString.contains(subString)) { sBuffer.append(subString + ","); } } System.out.println(sBuffer); if (sBuffer.length() != 0) { break; } } String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,"); return split; } return null; } // 如果存在多个长度相同的最大相同子串:使用ArrayList // public List<String> getMaxSameSubString1(String str1, String str2) { // if (str1 != null && str2 != null) { // List<String> list = new ArrayList<String>(); // String maxString = (str1.length() > str2.length()) ? str1 : str2; // String minString = (str1.length() > str2.length()) ? str2 : str1; // // int len = minString.length(); // for (int i = 0; i < len; i++) { // for (int x = 0, y = len - i; y <= len; x++, y++) { // String subString = minString.substring(x, y); // if (maxString.contains(subString)) { // list.add(subString); // } // } // if (list.size() != 0) { // break; // } // } // return list; // } // // return null; // } @Test public void testGetMaxSameSubString() { String str1 = "abcwerthelloyuiodef"; String str2 = "cvhellobnmiodef"; String[] strs = getMaxSameSubString1(str1, str2); System.out.println(Arrays.toString(strs)); } // 第5题 @Test public void testSort() { String str = "abcwerthelloyuiodef"; char[] arr = str.toCharArray(); Arrays.sort(arr); String newStr = new String(arr); System.out.println(newStr); } }
String、StringBuffer、StringBuilder三者的异同?
String: 不可变的字符序列;底层使用char[ ]存储
StringBuffer: 可变的字符序列,线程安全,效率低;底层使用char[ ]存储
StringBuilder: 可变的字符序列,jdk5.0新增的,线程不安全,效率高。底层使用char[ ]存储
● 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)
● 改:replace(int start, int end, String str)修改一个字符串、setCharAt(int n ,char ch) 修改一个字符
● 查:charAt(int n )
● 插:insert(int offset, xxx)
● 长度:length()
● 遍历:for() + charAt(int n) 这个用得不是很多~
System类提供的public static long currentTimeMillis( )用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。(此方法适于计算时间差)
计算世界时间的主要标准有:
● UTC(Coordinated Universal Time)
● GMT(Greenwich Mean Time)
● CST(Central Standard Time)
//System类中的currentTimeMillis() @Test public void test1(){ long time = System.currentTimeMillis(); //返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。 //称为时间戳 System.out.println(time); }
java.util.Date类
|—java.sql.Date类
1.两个构造器的使用
(1)构造器一:Date():创建一个对应当前时间的Date对象
(2)构造器二:创建指定毫秒数的Date对象
2.两个方法的使用
(1)toString():显示当前时间的年、月、日、时、分、秒
(2)getTime():获取当前对象对应的时间戳(毫秒数)
3.java.sql.Date对应这数据库中的日期类型的变量
(1)如何实例化? new + …
(2)sql.Date对象 --> util.Date对象(多态即可)
(3)util.Date对象 --> sql.Date对象
package com.java.api; import org.junit.Test; import java.util.Date; /** * @description: * java.util.Date类的使用 * @author: Fish_Vast * @Date: 2021/9/23 * @version: 1.0 */ public class DateTimeTest { @Test public void test2(){ //构造器一:Date():创建一个对应当前时间的Date对象 Date date1 = new Date(); System.out.println(date1.toString()); //Thu Sep 23 17:13:35 CST 2021 System.out.println(date1.getTime()); //1632388415406 //构造器二:创建指定毫秒数的Date对象 Date date2 = new Date(1632388415406L); System.out.println(date2.toString()); //创建java.sql.Date对象 java.sql.Date date3 = new java.sql.Date(265989494944L); System.out.println(date3.toString()); //1978-06-06 //util.Date对象 --> sql.Date对象 //情况一 Date date = new java.sql.Date(25448914948146L); java.sql.Date date4 = (java.sql.Date) date; System.out.println(date4.toString()); //情况二 Date date5 = new Date(); java.sql.Date date6 = new java.sql.Date(date5.getTime()); System.out.println(date6.toString()); } }
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
1.实例化SimpleDateFormat
2.两个操作:
(1)格式化:日期–>字符串
(2)解析:字符串–>日期
package com.java.api; import org.junit.Test; import java.text.ParseException; import java.text.SimpleDateFormat; /** * @description: * jdk8之前的日期时间的API测试:SimpleDateFormat * @author: Fish_Vast * @Date: 2021/9/24 * @version: 1.0 */ public class DateTimeTest2 { @Test public void simpleDateFormatTest() throws ParseException { //实例化SimpleDateFormat:使用默认的构造器 SimpleDateFormat sdf = new SimpleDateFormat(); //格式化:日期-->字符串 Date date = new Date(); System.out.println(date); String format = sdf.format(date); System.out.println(format); //解析:字符串-->日期 String str = "21-9-24 上午9:21"; Date date1 = sdf.parse(str); System.out.println(date1); System.out.println("*****************"); //按照指定的方式格式化和解析:调用带参的构造器 SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //格式化 String format1 = sdf1.format(date); System.out.println(format1); //解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),否则抛异常。 String str1 = "2021-10-24 09:26:48"; Date date2 = sdf1.parse(str1); System.out.println(date2); } //练习1:将字符串“2021-09-24”转换为java.sql.Date(需要掌握的内容!) @Test public void ExerciseTest() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //相当于解析的过程 String str = "2021-09-24"; Date date = sdf.parse(str); java.sql.Date date1 = new java.sql.Date(date.getTime()); System.out.println(date1); } //练习2:“三天打渔两天晒网” 1990-01-01 xxxx-xx-xx 打渔还是晒网? //算总天数: //总天数 % 5 == 1,2,3 打渔 //总天数 % 5 == 4,0 晒网 //总天数的计算: //方式一:(date1.getTime() - date2.getTime()) / (1000 * 60 * 60 * 24) +1 //方式二:1990-01-01 --> 2020-12-31 + 2021-01-01 --> 2021-09-24 (考虑是否是闰年) }
Calendar 日历类(抽象类)的使用
1.get()
2.set()
3.add()
4.getTime()
5.setTime()
注意:
(1) 获取月份时: 一月是0,二月是1,以此类推, 12月是11;
(2)获取星期时: 周日是1,周二是2 , 、、、,周六是7。
package com.java.api; import org.junit.Test; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * @description: * jdk8之前的日期时间的API测试:Calendar * @author: Fish_Vast * @Date: 2021/9/24 * @version: 1.0 */ public class DateTimeTest2 { @Test public void CalendarTest(){ //实例化 //方式1:多态 Calendar calendar = new GregorianCalendar(); //方式2:调用其静态方法getInstance() Calendar calendar1 = Calendar.getInstance(); System.out.println(calendar1.getClass()); //常用方法 //get() int day = calendar1.get(Calendar.DAY_OF_MONTH); System.out.println(day); System.out.println(calendar1.get(Calendar.DAY_OF_YEAR)); //set() //calendar:可变性 calendar1.set(Calendar.DAY_OF_MONTH,21); System.out.println(calendar1.get(Calendar.DAY_OF_MONTH)); //add() calendar1.add(Calendar.DAY_OF_MONTH,3); System.out.println(calendar1.get(Calendar.DAY_OF_MONTH)); calendar1.add(Calendar.DAY_OF_MONTH,-3); System.out.println(calendar1.get(Calendar.DAY_OF_MONTH)); //getTime():日历类 --> Date Date date = calendar1.getTime(); System.out.println(date); //setTime(): Date --> 日历类 Date date1 = new Date(); calendar1.setTime(date1); day = calendar1.get(Calendar.DAY_OF_MONTH); System.out.println(day); System.out.println(calendar1.get(Calendar.DAY_OF_YEAR)); } }
1.java.time – 包含值对象的基础包 2.java.time.chrono – 提供对不同的日历系统的访问 3.java.time.format – 格式化和解析时间和日期 4.java.time.temporal – 包括底层框架和扩展特性 5.java.time.zone – 包含时区支持的类
说明: 其实大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。在此,本文只介绍并记录开发中用得较多的相关新API。
LocalDate、 LocalTime、 LocalDateTime 类是基础包中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。
● LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
● LocalTime表示一个时间,而不是日期。
● LocalDateTime是用来表示日期和时间的, 这是一个最常用的类之一。
注明: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
方法 | 描述 |
---|---|
now() / * now(ZoneId zone) | 静态方法, 根据当前时间创建对象/指定时区的对象 |
of() | 静态方法, 根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、 分钟、 秒 |
withDayOfMonth()/withDayOfYear()/withMonth()/withYear() | 将月份天数、 年份天数、 月份、 年份修改为指定的值并返回新的对象 |
plusDays(), plusWeeks(),plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、 几周、 几个月、 几年、 几小时 |
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours() | 从当前对象减去几月、 几周、 几天、 几年、 几小时 |
package com.java.api; import org.junit.Test; import java.time.*; /** * @description: * LocalDate、 LocalTime、 LocalDateTime的使用 * 说明:LocalDateTime的使用频率更高一点 * @author: Fish_Vast * @Date: 2021/9/24 * @version: 1.0 */ public class JDK8DateTimeTest { @Test public void test(){ //now():获取时间、日期、时间+日期 LocalDate now = LocalDate.now(); LocalTime time = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(now); System.out.println(time); System.out.println(localDateTime); //of():设置指定的的年月日时分秒,并且没有偏移量 LocalDateTime localDateTime1 = localDateTime.of(2021, 9, 24, 15, 56, 30); System.out.println(localDateTime1); //getXxx() System.out.println(localDateTime.getDayOfMonth()); System.out.println(localDateTime.getDayOfYear()); System.out.println(localDateTime.getDayOfWeek()); System.out.println(localDateTime.getMonth()); System.out.println(localDateTime.getMinute()); //体现不可变性,类似于String //withXxx():设置相关属性 LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(22); System.out.println(localDateTime); System.out.println(localDateTime2); //plusXxx():添加相关属性 LocalDateTime localDateTime3 = localDateTime.plusDays(2); System.out.println(localDateTime); System.out.println(localDateTime3); //MinusXxx():减去相关属性 LocalDateTime localDateTime4 = localDateTime.minusDays(3); System.out.println(localDateTime); System.out.println(localDateTime4); } }
Instant的使用:类似于java.util.Date类
● Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
● java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如:时区。概念上讲, 它只是简单的表示自1970年1月1日0时0分0秒( UTC)开始的秒数。 因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳级。
注明:(1 ns = 10-9 s) 1 秒 = 1000 毫秒 = 106 微秒 = 109 纳秒
方法 | 描述 |
---|---|
now() | 静态方法, 返回默认UTC时区的Instant类的对象 |
ofEpochMilli(long epochMilli) | 静态方法,返回在 1970-01-01 00:00:00基础上加上指定毫秒数后的Instant类的对象 |
atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个 OffsetDateTime |
toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数, 即为时间戳 |
package com.java.api; import org.junit.Test; import java.time.*; /** * @description: * Instant的使用:类似于java.util.Date类 * @author: Fish_Vast * @Date: 2021/9/24 * @version: 1.0 */ public class JDK8DateTimeTest { @Test public void test2(){ //now():获取本初子午线对应的标准时间 Instant instant = Instant.now(); System.out.println(instant);//2021-09-24T08:18:41.534Z //添加时间的偏移量(例如北京时间是在“东八区”) OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime);//2021-09-24T16:23:13.549+08:00(这个才是我们所在时区的正常时间) //获取瞬时对应的毫秒数(返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳) -->Date类的getTime() long l = instant.toEpochMilli(); System.out.println(l); //ofEpochMilli:通过给定的毫秒数,获取Instant实例 -->Date(long millis) Instant instant1 = instant.ofEpochMilli(1632471921477L); System.out.println(instant1); } }
DateTimeFormatter:类似于SimpleDataFormat
方 法 | 描 述 |
---|---|
ofPattern(String pattern) | 静态方法 , 返回一个指定字符串格式的DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、 时间, 返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、 时间 |
package com.java.api; import com.sun.org.apache.xalan.internal.xsltc.compiler.Parser; import org.junit.Test; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.temporal.TemporalAccessor; /** * @description: * DateTimeFormatter的使用:类似于SimpleDataFormat * @author: Fish_Vast * @Date: 2021/9/24 * @version: 1.0 */ public class JDK8DateTimeTest { @Test public void test3(){ //方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME (用得很少) DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; //格式化 LocalDateTime localDateTime = LocalDateTime.now(); String str1 = dateTimeFormatter.format(localDateTime); System.out.println(localDateTime); System.out.println(str1);//2021-09-24T16:54:13.919 //解析 TemporalAccessor accessor = dateTimeFormatter.parse("2021-09-24T16:52:42.782"); System.out.println(accessor);//{},ISO resolved to 2021-09-24T16:52:42.782 //方式二:本地相关的格式。 //1.本地相关的格式。如:ofLocalizedDateTime() //FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT:(适用于localDateTime) DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); //格式化 String str2 = dateTimeFormatter1.format(localDateTime); System.out.println(str2);//2021年9月24日 下午05时00分16秒 //解析 TemporalAccessor accessor1 = dateTimeFormatter1.parse("2021年9月24日 下午05时00分16秒"); System.out.println(accessor1);//{},ISO resolved to 2021-09-24T17:00:16 //2.本地相关的格式。如:ofLocalizedDate() //FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT:(适用于localDate) DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); //格式化 String str3 = dateTimeFormatter2.format(LocalDate.now()); System.out.println(str3);//2021年9月24日 星期五 //解析 TemporalAccessor accessor2 = dateTimeFormatter2.parse("2021年9月24日 星期五"); System.out.println(accessor2);//{},ISO resolved to 2021-09-24 //重点是:*****方式三:自定义的格式。如: ofPattern(“yyyy-MM-dd hh:mm:ss”)**** DateTimeFormatter dateTimeFormatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); //格式化 String str4 = dateTimeFormatter3.format(localDateTime); System.out.println(str4);//2021-09-24 05:08:24(按照12小时制来计算的) //解析 TemporalAccessor accessor3 = dateTimeFormatter3.parse("2021-09-24 05:08:24"); System.out.println(accessor3);//{MinuteOfHour=8, MilliOfSecond=0, NanoOfSecond=0, HourOfAmPm=5, SecondOfMinute=24, MicroOfSecond=0},ISO resolved to 2021-09-24 } }
● ZoneId: 该类中包含了所有的时区信息, 一个时区的ID, 如 Europe/Paris。
● ZonedDateTime: 一个在ISO-8601日历系统时区的日期时间, 如 2007-12-03T10:15:30+01:00 Europe/Paris。其中每个时区都对应着ID, 地区ID都为“ {区域}/{城市}” 的格式, 例如:Asia/Shanghai等。
● Clock: 使用时区提供对当前即时、 日期和时间的访问的时钟。
● 持续时间: Duration, 用于计算两个“时间” 间隔。
● 日期间隔: Period, 用于计算两个“日期” 间隔。
● TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
● TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
//ZoneId:类中包含了所有的时区信息 // ZoneId的getAvailableZoneIds():获取所有的ZoneId Set<String> zoneIds = ZoneId.getAvailableZoneIds(); for (String s : zoneIds) { System.out.println(s); } // ZoneId的of():获取指定时区的时间 LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo")); System.out.println(localDateTime); //ZonedDateTime:带时区的日期时间 // ZonedDateTime的now():获取本时区的ZonedDateTime对象 ZonedDateTime zonedDateTime = ZonedDateTime.now(); System.out.println(zonedDateTime); // ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象 ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo")); System.out.println(zonedDateTime1); //Duration:用于计算两个“时间”间隔,以秒和纳秒为基准 LocalTime localTime = LocalTime.now(); LocalTime localTime1 = LocalTime.of(15, 23, 32); //between():静态方法,返回Duration对象,表示两个时间的间隔 Duration duration = Duration.between(localTime1, localTime); System.out.println(duration); System.out.println(duration.getSeconds()); System.out.println(duration.getNano()); LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32); LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32); Duration duration1 = Duration.between(localDateTime1, localDateTime); System.out.println(duration1.toDays()); //Period:用于计算两个“日期”间隔,以年、月、日衡量 LocalDate localDate = LocalDate.now(); LocalDate localDate1 = LocalDate.of(2028, 3, 18); Period period = Period.between(localDate, localDate1); System.out.println(period); System.out.println(period.getYears()); System.out.println(period.getMonths()); System.out.println(period.getDays()); Period period1 = period.withYears(2); System.out.println(period1); // TemporalAdjuster:时间校正器 // 获取当前日期的下一个周日是哪天? TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY); LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster); System.out.println(localDateTime); // 获取下一个工作日是哪天? LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() { @Override public Temporal adjustInto(Temporal temporal) { LocalDate date = (LocalDate) temporal; if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) { return date.plusDays(3); } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) { return date.plusDays(2); } else { return date.plusDays(1); } } }); System.out.println("下一个工作日是: " + localDate);
Java中的对象,正常情况下,只能进行比较:== 或 !=,不能使用< 或 > 的。但是在开发环境下,我们需要对多个对象进行排序,就需要比较对象的大小。
使用两个接口中的任何一个:Comparable 或 Comparator
① 像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较对象大小的方式
② 像String、包装类重写了compareTo(obj)方法以后,进行了从小到大的排序
③ 重写compareTo()的规则:
(3.1)如果当前对象this大于形参对象obj, 则返回正整数;
(3.2)如果当前对象this小于形参对象obj, 则返回负整数;
(3.3)如果当前对象this等于形参对象obj, 则返回零。
④ 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法,在compareTo(obj)方法中指明如何排序。
① 背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序。
② 重写规则:
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
(2.1)如果方法返回正整数,则表示o1大于o2;
(2.2)如果返回0,表示相等;
(2.3)返回负整数,表示o1小于o2。
package com.java.api; import org.junit.Test; import java.util.Arrays; import java.util.Comparator; /** * @description: * 1.Comparable接口的使用(自然排序) * 2.Comparator接口的使用(定制排序) * @author: Fish_Vast * @Date: 2021/9/27 * @version: 1.0 */ public class CompareTest { /* Comparable接口使用举例:(自然排序) */ @Test public void test(){ String[] arr = new String[]{"MM","AA","BB","CC","GG","DD","FF"}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } @Test public void test1(){ Goods [] arr = new Goods[5]; arr[0] = new Goods("华为",450); arr[1] = new Goods("苹果",350); arr[2] = new Goods("小米",350); arr[3] = new Goods("魅族",150); arr[4] = new Goods("联想",100); Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } /* Comparator接口使用举例:(定制排序) */ @Test public void test2(){ String[] arr = new String[]{"MM","AA","BB","CC","GG","DD","FF"}; 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); } throw new RuntimeException("输入的数据类型不一致!"); } }); System.out.println(Arrays.toString(arr)); } @Test public void test3(){ Goods [] arr = new Goods[5]; arr[0] = new Goods("华为",450); arr[1] = new Goods("苹果",350); arr[2] = new Goods("小米",350); arr[3] = new Goods("魅族",150); arr[4] = new Goods("联想",100); Arrays.sort(arr, new Comparator(){ //指明商品比较大小的方式:按照名称从低到高的方式排序,再按价格从高到低排序。 @Override public int compare(Object o1, Object o2) { if(o1 instanceof Goods && o2 instanceof Goods){ Goods s1 = (Goods) o1; Goods s2 = (Goods) o2; if(s1.getName().equals(((Goods) o2).getName())){ return Double.compare(s1.getPrice(), s2.getPrice()); }else{ return s1.getName().compareTo(s2.getName()); } } throw new RuntimeException("传入的数据类型不一致!"); } }); System.out.println(Arrays.toString(arr)); } }
package com.java.api; /** * @description: * Goods实体类 * @author: Fish_Vast * @Date: 2021/9/27 * @version: 1.0 */ 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 -this.name.compareTo(goods.name); //因为String类中已重写了compareTo,直接用即可。 //加个“-”,就是反向排序的意思,从低到高 --> 从高到低 } //方式二 // return Double.compare(this.price, goods.price); } throw new RuntimeException("传入的数据类型不一致!"); } }
① Comparable接口的方式一旦指定,保证Comparator接口实现类的对象在任何位置都可以比较大小;(反复使用)
② Comparator接口则属性临时性的比较。(一次性使用)
● System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
● 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的, 所以也可以很方便的进行调用。
● 成员变量
▷ System类内部包含in、 out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
● 成员方法
▷ native long currentTimeMillis():
该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
▷ void exit(int status):
该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。 使用该方法可以在图形界面编程中实现程序的退出功能等。
▷ void gc():
该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
▷ String getProperty(String key):
该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
属性名 | 属性说明 |
---|---|
java.version | Java运行时环境版本 |
java.home | Java安装目录 |
os.home | 操作系统的名称 |
os.version | 操作系统的版本 |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
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类
● Integer类作为int的包装类,能存储的最大整型值为231 -1, Long类也是有限的,最大为 263 -1。 如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
● java.math包的BigInteger可以表示不可变的任意精度的整数。
● 构造器
▷ BigInteger(String val): 根据字符串构建BigInteger对象
● 常用方法
▷ 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。
(二)BigDecimal类
● 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。
● BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
● 构造器
▷ public BigDecimal(double val)
▷ public BigDecimal(String val)
● 常用方法
▷ public BigDecimal add(BigDecimal augend)
▷ public BigDecimal subtract(BigDecimal subtrahend)
▷ public BigDecimal multiply(BigDecimal multiplicand)
▷ public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
package com.java.api; import org.junit.Test; import java.math.BigDecimal; import java.math.BigInteger; /** * @description: 其他常用类的使用: * System类 * Math类 * BigInteger与BigDecimal类 * @author: Fish_Vast * @Date: 2021/9/27 * @version: 1.0 */ public class OtherClassTest { @Test 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); } @Test public void test2() { BigInteger bi = new BigInteger("1244648919494219"); BigDecimal bd = new BigDecimal("12435.3545611"); BigDecimal bd2 = new BigDecimal("11"); System.out.println(bi); // System.out.println(bd.divide(bd2)); System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP)); System.out.println(bd.divide(bd2, 45, BigDecimal.ROUND_HALF_UP)); } }