01、字符串相关的类 1.1、String类的概述 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import org.junit.Test;public class StringTest { @Test public void Test1 () { } }
1.2、理解String的不可变性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import org.junit.Test;public class StringTest { @Test public void Test1 () { String s1 = "abc" ; String s2 = "abc" ; s1 = "hello" ; System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); System.out.println("*********************" ); String s3 = "abc" ; s3 += "def" ; System.out.println(s3); System.out.println("**********************" ); String s4 = "abc" ; String s5 = s4.replace('a' , 'm' ); System.out.println(s4); System.out.println(s5); } }
1.3、String不同实例化方式的对比 1、String对象的创建
1 2 3 4 5 6 7 8 9 10 11 12 String str = "hello" ;String s1 = new String (); String s2 = new String (String original); String s3 = new String (char [] a);String s4 = new String (char [] a,int startIndex,int count);
2、String str1 = “abc”;与String str2 = new String(“abc”);的区别?
字符串常量存储在字符串常量池,目的是共享 字符串非常量对象存储在堆中。
3、练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import org.junit.Test;public class StringTest { @Test public void test2 () { String s1 = "javaEE" ; String s2 = "javaEE" ; String s3 = new String ("javaEE" ); String s4 = new String ("javaEE" ); System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1 == s4); System.out.println(s3 == s4); System.out.println("***********************" ); Person p1 = new Person ("Tom" ,12 ); Person p2 = new Person ("Tom" ,12 ); System.out.println(p1.name.equals(p2.name)); System.out.println(p1.name == p2.name); p1.name = "Jerry" ; System.out.println(p2.name); } }
Person类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Person { String name; int age; public Person (String name, int age) { this .name = name; this .age = age; } public Person () { } }
1.4、String不同拼接操作的对比 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import org.junit.Test;public class StringTest { @Test public void test4 () { String s1 = "javaEEhadoop" ; String s2 = "javaEE" ; String s3 = s2 + "hadoop" ; System.out.println(s1 == s3); final String s4 = "javaEE" ; String s5 = s4 + "hadoop" ; System.out.println(s1 == s5); } @Test public void test3 () { 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); System.out.println(s3 == s5); System.out.println(s3 == s6); System.out.println(s5 == s6); System.out.println(s3 == s7); System.out.println(s5 == s6); System.out.println(s5 == s7); System.out.println(s6 == s7); String s8 = s5.intern(); System.out.println(s3 == s8); } }
1.4.1、String使用陷阱 1、String s1 = “a”;
说明:在字符串常量池中创建了一个字面量为"a"的字符串。
2、s1 = s1 + “b”;
说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符串s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。
3、String s2 = “ab”;
说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。
4、String s3 = “a” + “b”;
说明:s3指向字符串常量池中已经创建的"ab"的字符串。
5、String s4 = s1.intern();
说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的"ab"字符串赋值给s4。
6、练习
1.5、String的一道面试题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class StringTest { String str = new String ("good" ); char [] ch = { 't' , 'e' , 's' , 't' }; public void change (String str, char ch[]) { str = "test ok" ; ch[0 ] = 'b' ; } public static void main (String[] args) { StringTest ex = new StringTest (); ex.change(ex.str, ex.ch); System.out.println(ex.str); System.out.println(ex.ch); } }
1.6、JVM中涉及字符串的内存结构
1.7、String的常用方法1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import org.junit.Test;public class StringMethodTest { @Test public void test2 () { String s1 = "HelloWorld" ; String s2 = "helloworld" ; System.out.println(s1.equals(s2)); System.out.println(s1.equalsIgnoreCase(s2)); String s3 = "abc" ; String s4 = s3.concat("def" ); System.out.println(s4); String s5 = "abc" ; String s6 = new String ("abe" ); System.out.println(s5.compareTo(s6)); String s7 = "周围好吵啊" ; String s8 = s7.substring(2 ); System.out.println(s7); System.out.println(s8); String s9 = s7.substring(0 , 2 ); System.out.println(s9); } @Test public void Test1 () { String s1 = "helloworld" ; System.out.println(s1.length()); 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(); System.out.println(s1); System.out.println(s2); String s3 = " he llo world " ; String s4 = s3.trim(); System.out.println("-----" + s3 + "-----" ); System.out.println("-----" + s4 + "-----" ); } }
1.8、String的常用方法2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import org.junit.Test;public class StringMethodTest { @Test public void test3 () { String str1 = "helloworld" ; boolean b1 = str1.endsWith("rld" ); System.out.println(b1); boolean b2 = str1.startsWith("He" ); System.out.println(b2); boolean b3 = str1.startsWith("ll" ,2 ); System.out.println(b3); String str2 = "wor" ; System.out.println(str1.contains(str2)); System.out.println(str1.indexOf("lo" )); System.out.println(str1.indexOf("lo" ,5 )); String str3 = "hellorworld" ; System.out.println(str3.lastIndexOf("or" )); System.out.println(str3.lastIndexOf("or" ,6 )); } }
1.9、String的常用方法3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import org.junit.Test;public class StringMethodTest { @Test public void test4 () { String str1 = "西藏布达拉宫欢迎您" ; String str2 = str1.replace('西' ,'东' ); System.out.println(str1); System.out.println(str2); String str3 = str1.replace("北京" , "南京" ); System.out.println(str3); System.out.println("*************************" ); String str = "12hello34world5java7891mysql456" ; String string = str.replaceAll("\\d+" , "," ).replaceAll("^,|,$" , "" ); System.out.println(string); System.out.println("*************************" ); str = "12345" ; 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); System.out.println("*************************" ); str = "hello|world|java" ; String[] strs = str.split("\\|" ); for (int i = 0 ; i < strs.length; i++) { System.out.println(strs[i]); } System.out.println(); str2 = "hello.world.java" ; String[] strs2 = str2.split("\\." ); for (int i = 0 ; i < strs2.length; i++) { System.out.println(strs2[i]); } } }
1.10、String与基本数据类型包装类的转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import org.junit.Test;public class StringTest1 { @Test public void test1 () { String str1 = "123" ; int num = Integer.parseInt(str1); String str2 = String.valueOf(num); String str3 = num + "" ; System.out.println(str1 == str3); } }
1.11、String与char[]之间的转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import org.junit.Test;public class StringTest1 { @Test public void test2 () { String str1 = "abc123" ; char [] charArray = str1.toCharArray(); for (int i = 0 ; i < charArray.length; i++) { System.out.println(charArray[i]); } char [] arr = new char []{'h' ,'e' ,'l' ,'l' ,'o' }; String str2 = new String (arr); System.out.println(str2); } }
1.12、String与byte[]之间的转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import org.junit.Test;import java.io.UnsupportedEncodingException;import java.util.Arrays;public class StringTest1 { @Test public void test3 () throws UnsupportedEncodingException { String str1 = "abc123重工" ; byte [] bytes = str1.getBytes(); System.out.println(Arrays.toString(bytes)); byte [] gbks = str1.getBytes("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); } }
1.13、面试中String算法考查的说明 1、模拟一个trim方法,去除字符串两端的空格。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import org.junit.Test;public class StringExer { 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 ; } @Test public void testMyTrim () { String str = " a " ; String newStr = myTrim(str); System.out.println("---" + newStr + "---" ); } }
2、将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 import org.junit.Test;public class StringDemo { public String reverse (String str,int startIndex,int endIndex) { if (str != null && str.length() != 0 ) { char [] arr = str.toCharArray(); for (int x = startIndex, y = endIndex; x < y; x++, y--) { char temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } return new String (arr); } return null ; } public String reverse2 (String str, int startIndex, int endIndex) { if (str != null ) { String reverStr = str.substring(0 ,startIndex); for (int i = endIndex; i >= startIndex; i--) { reverStr += str.charAt(i); } reverStr += str.substring(endIndex + 1 ); return reverStr; } return null ; } public String reverse3 (String str, int startIndex, int endIndex) { StringBuilder builder = new StringBuilder (str.length()); if (str != null ) { builder.append(str.substring(0 , startIndex)); for (int i = endIndex; i >= startIndex; i--) { builder.append(str.charAt(i)); } builder.append(str.substring(endIndex + 1 )); return builder.toString(); } return null ; } @Test public void testReverse () { String str = "abcdefg" ; String str1 = reverse3(str, 2 , 5 ); System.out.println(str1); } }
3、获取一个字符串在另一个字符串中出现的次数。比如:获取“ ab”在“abkkcadkabkebfkabkskab” 中出现的次数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import org.junit.Test;public class StringDemo2 { public int getCount (String mainStr,String subStr) { int mainLength = mainStr.length(); int subLength = subStr.length(); int count = 0 ; int index = 0 ; if (mainLength >= subLength){ while ((index = mainStr.indexOf(subStr,index)) != -1 ){ count++; index += subLength; } return count; }else { return 0 ; } } @Test public void testGetCount () { String mainStr = "abkkcadkabkebfkabkskab" ; String subStr = "ab" ; int count = getCount(mainStr,subStr); System.out.println(count); } }
4、获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”
提示:将短的那个串进行长度依次递减的子串与较长的串比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import org.junit.Test;import java.util.Arrays;public class StringDemo3 { public String getMaxSameString (String str1,String str2) { if (str1 != null && str2 != null ){ String maxStr = (str1.length() >= str2.length())? str1 : str2; String minStr = (str1.length() < str2.length())? str1 : str2; int length = minStr.length(); for (int i = 0 ;i < length;i++){ for (int x = 0 ,y = length - i;y <= length;x++,y++){ String subStr = minStr.substring(x,y); if (maxStr.contains(subStr)){ return subStr; } } } } return null ; } public String[] getMaxSameString1(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 + "," ); } } if (sBuffer.length() != 0 ) { break ; } } String[] split = sBuffer.toString().replaceAll(",$" , "" ).split("\\," ); return split; } return null ; } @Test public void testGetMaxSameString () { String str1 = "abcwerthello1yuiodefabcdef" ; String str2 = "cvhello1bnmabcdef" ; String[] maxSameStrings = getMaxSameString1(str1, str2); System.out.println(Arrays.toString(maxSameStrings)); } }
5、对字符串中字符进行自然顺序排序。
提示:
1)字符串变成字符数组。
2)对数组排序,选择,冒泡,Arrays.sort();
3)将排序后的数组变成字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import org.junit.Test;import java.util.Arrays;public class StringDemo4 { @Test public void testSort () { String str = "abcwerthelloyuiodef" ; char [] arr = str.toCharArray(); Arrays.sort(arr); String newStr = new String (arr); System.out.println(newStr); } }
1.14、StringBuffer和StringBuilder的介绍 1.15、StringBuffer的源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import org.junit.Test;public class StringBufferBuilderTest { @Test public void test1 () { StringBuffer sb1 = new StringBuffer ("abc" ); sb1.setCharAt(0 ,'m' ); System.out.println(sb1); StringBuffer sb2 = new StringBuffer (); System.out.println(sb2.length()); } }
1.16、StringBuffer中的常用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import org.junit.Test;public class StringBufferBuilderTest { @Test public void test2 () { StringBuffer s1 = new StringBuffer ("abc" ); s1.append(1 ); s1.append('1' ); System.out.println(s1); String s2 = s1.substring(1 ,3 ); System.out.println(s1); System.out.println(s1.length()); System.out.println(s2); } }
1.17、String、StringBuffer、StringBuilder效率对比 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import org.junit.Test;public class StringBufferBuilderTest { @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)); } }
02、JDK 8之前的日期时间API
2.1、System类中获取时间戳的方法 System
类提供的public static long currentTimeMillis()
用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
此方法适于计算时间差。 计算世界时间的主要标准有:UTC(Coordinated Universal Time) GMT(Greenwich Mean Time) CST(Central Standard Time) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import org.junit.Test;public class DateTimeTest { @Test public void test1 () { long time = System.currentTimeMillis(); System.out.println(time); } }
2.2、Java中两个Date类的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import org.junit.Test;import java.util.Date;public class DateTimeTest { @Test public void test2 () { Date date1 = new Date (); System.out.println(date1.toString()); System.out.println(date1.getTime()); Date date2 = new Date (1589026216998L ); System.out.println(date2.toString()); java.sql.Date date3 = new java .sql.Date(35235325345L ); System.out.println(date3); Date date6 = new Date (); java.sql.Date date7 = new java .sql.Date(date6.getTime()); } }
03、JDK 8之前的日期时间API Date
类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat
类是一个不与语言环境有关的方式来格式化和解析日期的具体类。它允许进行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import org.junit.Test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class DateTime { @Test public void testSimpleDateFormat () throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat (); Date date = new Date (); System.out.println(date); String format = sdf.format(date); System.out.println(format); String str = "19-12-18 上午11:43" ; Date date1 = sdf.parse(str); System.out.println(date1); SimpleDateFormat sdf1 = new SimpleDateFormat ("yyyyy.MMMMM.dd GGG hh:mm aaa" ); String format1 = sdf1.format(date); System.out.println(format1); Date date2 = sdf1.parse("02020.五月.10 公元 04:32 下午" ); System.out.println(date2); } }
1、练习1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import org.junit.Test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class DateTime { @Test public void testExer () throws ParseException { String birth = "2020-09-08" ; SimpleDateFormat sdf1 = new SimpleDateFormat ("yyyy-MM-dd" ); Date date = sdf1.parse(birth); java.sql.Date birthDate = new java .sql.Date(date.getTime()); System.out.println(birthDate); } }
2、练习2
3.3、Calendar日历类的使用 Calendar
是一个抽象基类,主用用于完成日期字段之间相互操作的功能。获取Calendar
实例的方法使用Calendar.getInstance()
方法 调用它的子类GregorianCalendar
的构造器。 一个Calendar的实例是系统时间的抽象表示,通过get(intfield)
方法来取得想要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、MINUTE、SECOND
public void set(intfield,intvalue)
public void add(intfield,intamount)
public final Date getTime()
public final void setTime(Date date)
注意:获取月份时:一月是0,二月是1,以此类推,12月是11 获取星期时:周日是1,周二是2,。。。。周六是7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import java.util.Calendar;import java.util.Date;import org.junit.Test;public class DateTime { @Test public void testCalendar () { Calendar calendar = Calendar.getInstance(); int days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); calendar.set(Calendar.DAY_OF_MONTH,22 ); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); calendar.add(Calendar.DAY_OF_MONTH,-3 ); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); Date date = calendar.getTime(); System.out.println(date); Date date1 = new Date (); calendar.setTime(date1); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); } }
04、JDK8中日期时间API的介绍 1、新日期时间API出现的背景
如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
可变性:像日期和时间这样的类应该是不可变的。 偏移性:Date中的年份是从1900开始的,而月份都从0开始。 格式化:格式化只对Date有用,Calendar则不行。 此外,它们也不是线程安全的;不能处理闰秒等。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import org.junit.Test;import java.util.Date;public class JDK8DateTimeTest { @Test public void testDate () { Date date1 = new Date (2020 ,9 ,8 ); System.out.println(date1); Date date2 = new Date (2020 - 1900 ,9 - 1 ,8 ); System.out.println(date2); } }
第三次引入的API是成功的,并且Java 8中引入的java.time
API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了Joda-Time 的精华,以一个新的开始为Java 创建优秀的API。新的java.time
中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类 。历史悠久的Date 类新增了toInstant()
方法,用于把Date 转换成新的表示形式。这些新增的本地化时间日期API 大大简化了日期时间和本地化的管理。
1 2 3 4 java.time–包含值对象的基础包 java.time.chrono–提供对不同的日历系统的访问java.time.format–格式化和解析时间和日期java.time.temporal–包括底层框架和扩展特性java.time.zone–包含时区支持的类 说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽管有68 个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。
4.1、LocalDate、LocalTime、LocalDateTime的使用 LocalDate、LocalTime、LocalDateTime
类是其中较重要的几个类,它们的实例是不可变的对象 ,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。LocalDate
代表IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期。LocalTime
表示一个时间,而不是日期。LocalDateTime
是用来表示日期和时间的,这是一个最常用的类之一 。注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 import org.junit.Test;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;public class JDK8DateTimeTest { @Test public void test1 () { LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDate); System.out.println(localTime); System.out.println(localDateTime); LocalDateTime localDateTime1 = LocalDateTime.of(2020 , 10 , 6 , 13 , 23 , 43 ); System.out.println(localDateTime1); System.out.println(localDateTime.getDayOfMonth()); System.out.println(localDateTime.getDayOfWeek()); System.out.println(localDateTime.getMonth()); System.out.println(localDateTime.getMonthValue()); System.out.println(localDateTime.getMinute()); LocalDate localDate1 = localDate.withDayOfMonth(22 ); System.out.println(localDate); System.out.println(localDate1); LocalDateTime localDateTime2 = localDateTime.withHour(4 ); System.out.println(localDateTime); System.out.println(localDateTime2); LocalDateTime localDateTime3 = localDateTime.plusMonths(3 ); System.out.println(localDateTime); System.out.println(localDateTime3); LocalDateTime localDateTime4 = localDateTime.minusDays(6 ); System.out.println(localDateTime); System.out.println(localDateTime4); } }
4.2、Instant类的使用 Instant
:时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳。在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。 java.time
包通过值类型Instan
t提供机器视图,不提供处理人类意义上的时间单位。Instant
表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time
包是基于纳秒计算的,所以Instant
的精度可以达到纳秒级。(1 ns = 10-9s) 1秒= 1000毫秒=106微秒=109纳秒
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import org.junit.Test;import java.time.*;public class JDK8DateTimeTest { @Test public void test2 () { Instant instant = Instant.now(); System.out.println(instant); OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8 )); System.out.println(offsetDateTime); long milli = instant.toEpochMilli(); System.out.println(milli); Instant instant1 = Instant.ofEpochMilli(1550475314878L ); System.out.println(instant1); } }
java.time.format.DateTimeFormatter
类:该类提供了三种格式化方法:
预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 import org.junit.Test;import java.time.*;import java.time.format.DateTimeFormatter;import java.time.format.FormatStyle;import java.time.temporal.TemporalAccessor;public class JDK8DateTimeTest { @Test public void test3 () { DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; LocalDateTime localDateTime = LocalDateTime.now(); String str1 = formatter.format(localDateTime); System.out.println(localDateTime); System.out.println(str1); TemporalAccessor parse = formatter.parse("2020-05-10T18:26:40.234" ); System.out.println(parse); DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); String str2 = formatter1.format(localDateTime); System.out.println(str2); DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM); String str3 = formatter2.format(LocalDate.now()); System.out.println(str3); DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss" ); String str4 = formatter3.format(LocalDateTime.now()); System.out.println(str4); TemporalAccessor accessor = formatter3.parse("2020-05-10 06:26:40" ); System.out.println(accessor); } }
4.4、其它日期时间相关API的使用 ZoneId:该类中包含了所有的时区信息,一个时区的ID,如Europe/Paris ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如2007-12-03T10:15:30+01:00Europe/Paris。其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import org.junit.Test;import java.time.*;import java.util.Set;public class JDK8DateTimeTest { @Test public void test1 () { Set<String> zoneIds= ZoneId.getAvailableZoneIds(); for (String s: zoneIds) { System.out.println(s); } LocalDateTime localDateTime= LocalDateTime.now(ZoneId.of("Asia/Tokyo" )); System.out.println(localDateTime); ZonedDateTime zonedDateTime= ZonedDateTime.now(); System.out.println(zonedDateTime); ZonedDateTime zonedDateTime1= ZonedDateTime.now(ZoneId.of("Asia/Tokyo" )); System.out.println(zonedDateTime1); } }
Clock:使用时区提供对当前即时、日期和时间的访问的时钟。 持续时间:Duration,用于计算两个“时间”间隔 日期间隔:Period,用于计算两个“日期”间隔 TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。 TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.time.Duration;import java.time.LocalDateTime;import java.time.LocalTime;import org.junit.Test;public class JDK8APITest { @Test public void test2 () { LocalTime localTime= LocalTime.now(); LocalTime localTime1= LocalTime.of(15 , 23 , 32 ); 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()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.time.Period;import org.junit.Test;public class JDK8APITest { @Test public void test3 () { 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); } }
4.4.1、参考:与传统日期处理的转换
05、Java比较器 5.1、概述 Java中的对象,正常情况下,只能进行比较:==
或 !=
。不能使用 >
或<
的,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。 如何实现?使用两个接口中的任何一个:Comparable
或 Comparator
Java实现对象排序的方式有两种:自然排序:java.lang.Comparable
定制排序:java.util.Comparator
5.2、Comparable自然排序举例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import org.junit.Test;import java.util.Arrays;public class CompareTest { @Test public void test1 () { String[] arr = new String []{"AA" ,"CC" ,"KK" ,"MM" ,"GG" ,"JJ" ,"DD" }; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } }
5.3、自定义类实现Comparable自然排序 1、测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import org.junit.Test;import java.util.Arrays;public class CompareTest { @Test 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、Goods类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 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); } } throw new RuntimeException ("传入的数据类型不一致!" ); } }
5.4、使用Comparator实现定制排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import org.junit.Test;import java.util.Arrays;import java.util.Comparator;public class CompareTest { @Test 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); } throw new RuntimeException ("输入的数据类型不一致" ); } }); System.out.println(Arrays.toString(arr)); } @Test 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)); }
Comparable接口与Comparator的使用的对比 :
Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。 Comparator接口属于临时性的比较。 06、System类、Math类、BigInteger与BigDecimal 6.1、System类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import org.junit.Test;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); } }
6.2、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) 角度—>弧度 6.3、BigInteger与BigDecimal Integer
类作为int
的包装类,能存储的最大整型值为2^31 -1
,Long
类也是有限的,最大为2^63 -1
。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。java.math
包的BigInteger
可以表示不可变的任意精度的整数。BigInteger
提供所有Java 的基本整数操作符的对应物,并提供java.lang.Math
的所有相关方法。另外,BigInteger
还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。构造器BigInteger(String val)
:根据字符串构建BigInteger
对象 常用方法 一般的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)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import org.junit.Test;import java.math.BigDecimal;import java.math.BigInteger;public class OtherClassTest { @Test public void test2 () { BigInteger bi = new BigInteger ("1243324112234324324325235245346567657653" ); BigDecimal bd = new BigDecimal ("12435.351" ); BigDecimal bd2 = new BigDecimal ("11" ); System.out.println(bi); System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP)); System.out.println(bd.divide(bd2, 25 , BigDecimal.ROUND_HALF_UP)); } }