1、工具類
Java中提供了大量的類和接口完成特定的功能。每個(gè)類都會(huì)有自己的屬性和行為(功能)。但是這些功能還是不能滿足所有的需求。于是Java中又對(duì)某些類提供的額外的功能。而把這些功能定義在特定的類中。
比如:集合類,每個(gè)集合類都提供可以操作自己這個(gè)集合容器中元素的函數(shù)。比如:添加元素、刪除元素、修改元素、獲取元素。而在開(kāi)發(fā)中,對(duì)集合操作時(shí),這些函數(shù)依然不夠用。例:對(duì)有角標(biāo)的集合進(jìn)行排序、獲取集合中最大值或者最小值等功能。于是Java又對(duì)這些集合類提供更多的功能,把這些功能定義在一個(gè)Collections類中。這個(gè)Collections類是一個(gè)專門給集合增加額外補(bǔ)充功能的類。
把這些專門提供補(bǔ)充或者額外增加功能的類在Java中稱為工具類。
工具類的特點(diǎn):
Java中所有的工具類中的函數(shù)全部都是靜態(tài)的。并且工具類一般都會(huì)保存在java.util包下。
補(bǔ)充:如果自己在開(kāi)發(fā)項(xiàng)目的時(shí)候,在整個(gè)項(xiàng)目中會(huì)專門建一個(gè)包來(lái)存放工具類的。
這個(gè)包我們一般這樣命名:cn.xuexi.utils。
1.1、Collections工具類介紹

Collections工具類,主要就是操作集合的。如果當(dāng)操作集合的時(shí)候,發(fā)現(xiàn)集合的方法不夠用了,這時(shí)一定要先到Collections工具類中找有沒(méi)有適合我們需求的功能。
Collections類中的常用方法:
1)

把可變參數(shù)指定的對(duì)象存放到指定的c集合中。
public static <T> boolean addAll(Collection<?> c,T... elements)

2)對(duì)指定的集合進(jìn)行排序。
public static <T> void sort(List<T> list)

3)二分法查找或者叫做折半查找。
說(shuō)明:使用二分法查找前提是一定要排序。否則查找的結(jié)果不是我們想要的。
public static <T> <u>int</u> binarySearch(List<?> list,T key)
需求:找一下12在集合中的位置。

注意:根據(jù)指定的集合中的元素找對(duì)應(yīng)的下標(biāo),如果指定的元素不在集合中。則返回(-(插入點(diǎn)) - 1),不是返回-1。按排序后插入數(shù)據(jù)。

4)求集合中元素的最大值。
public static <T> T max(Collection<?> <u>coll</u>)

5)把指定的list集合中的元素進(jìn)行反轉(zhuǎn)。
public static void reverse(List<?> list)

6) 打亂集合中的數(shù)據(jù)順序,這個(gè)函數(shù)經(jīng)常使用在寫撲克牌游戲中。
public static void shuffle(List<?> list)

代碼演示如下所示:
分析和步驟:
1)創(chuàng)建ArrayList<Integer>集合list,泛型是Integer;
2)使用集合對(duì)象list調(diào)用add函數(shù)向集合中添加幾個(gè)整數(shù)類型的數(shù)據(jù);
3)分別演示上述函數(shù)的功能;
package cn.xuexi.collections.demo;
import java.util.ArrayList;
import java.util.Collections;
/*
* Collections的其他函數(shù)演示
* public static <T> void sort(List<T> list) 對(duì)指定的集合進(jìn)行排序
* public static <T> int binarySearch(List<?> list,T key) 根據(jù)指定的集合中的元素查找對(duì)應(yīng)的下標(biāo)
* public static <T> T max(Collection<?> coll) 求集合中元素的最大值
* public static void reverse(List<?> list) 把指定的集合中的元素進(jìn)行反轉(zhuǎn)
* public static void shuffle(List<?> list) 打亂集合中數(shù)據(jù)
*/
public class CollectionsDemo1 {
public static void main(String[] args) {
// 創(chuàng)建集合對(duì)象
ArrayList<Integer> list = new ArrayList<Integer>();
//向集合中添加數(shù)據(jù)
Collections.addAll(list, 12,34,2,18,57);
//輸出原始的集合
System.out.println(list);
//對(duì)集合進(jìn)行排序
Collections.sort(list);
//輸出排序后的集合
System.out.println("排序后"+list);
//需求:找一下12在集合中的位置 list表示集合名,12表示集合中的數(shù)據(jù)
int index = Collections.binarySearch(list,12);
System.out.println(index);
//求集合中元素的最大值
Integer max = Collections.max(list);
System.out.println("max="+max);
//把指定集合中的元素進(jìn)行反轉(zhuǎn)
Collections.reverse(list);
System.out.println("反轉(zhuǎn)后的集合"+list);
//打亂集合中的數(shù)據(jù)
Collections.shuffle(list);
//輸出打亂后的集合數(shù)據(jù)
System.out.println("打亂后的集合"+list);
}
}
1.2、Arrays工具類介紹
Arrays它是數(shù)組的工具類:

Arrays工具類中提供數(shù)組的:二分查找,復(fù)制數(shù)組,填充數(shù)組,排序,把數(shù)組轉(zhuǎn)成字符串。但是沒(méi)有提供對(duì)數(shù)組中的數(shù)據(jù)進(jìn)行反轉(zhuǎn),求數(shù)組中的最值問(wèn)題。
如果我們能夠把數(shù)組轉(zhuǎn)成集合,就可以使用Collections工具類中的最值和反轉(zhuǎn)功能。
也就是說(shuō)數(shù)組轉(zhuǎn)換為集合的目的就是為了使用集合中的方法操作數(shù)組中的元素。
數(shù)組轉(zhuǎn)集合的函數(shù):

public static <T> List<T> asList(T... a)
數(shù)組轉(zhuǎn)成集合使用Arrays中的asList方法。
注意:將數(shù)組轉(zhuǎn)成集合需要注意以下幾點(diǎn):
1)將數(shù)組轉(zhuǎn)為一個(gè)集合,得到的集合長(zhǎng)度固定。集合長(zhǎng)度不能改變。
也就是說(shuō)數(shù)組轉(zhuǎn)換后的集合不能對(duì)集合增刪元素,元素可以修改。
2)使用asList函數(shù)將數(shù)組轉(zhuǎn)換為集合,由于asList函數(shù)的參數(shù)是可變參數(shù),可以接收數(shù)組;
3)如果數(shù)組中存儲(chǔ)的是引用數(shù)據(jù)類型的數(shù)據(jù),比如字符串String類等,那么返回值List<T>的泛型是是String,而不是String[] 。
因?yàn)閿?shù)組中保存的是引用數(shù)據(jù)類型的字符串對(duì)象,而集合是用來(lái)保存對(duì)象的,所以數(shù)組中的每個(gè)字符串對(duì)象數(shù)據(jù)都會(huì)放在集合中作為集合元素。
分析和步驟:
a.定義一個(gè)測(cè)試類ArraysDemo;
b.在這個(gè)類中的主函數(shù)中定義一個(gè)字符串?dāng)?shù)組,存儲(chǔ)幾個(gè)字符串,使用Arrays類調(diào)用asList()函數(shù)將數(shù)組轉(zhuǎn)換為集合;
c.由于asList()函數(shù)是可變參數(shù)也可以接收可變參數(shù),所以傳遞幾個(gè)字符串作為可變參數(shù)在生成一個(gè)新的集合;
d.分別使用上述生成集合的對(duì)象演示對(duì)集合增刪改操作,并輸出結(jié)果;
package cn.xuexi.arrays.demo;
import java.util.Arrays;
import java.util.List;
/*
* public static <T> List<T> asList(T... a)
* 使用上述函數(shù)將數(shù)組轉(zhuǎn)換為集合,然后可以使用集合中的函數(shù)來(lái)操作數(shù)組
* 注意:由于數(shù)組長(zhǎng)度是固定的,轉(zhuǎn)化為集合后,集合的長(zhǎng)度也不能被改變
*/
public class ArraysDemo {
public static void main(String[] args) {
//創(chuàng)建數(shù)組
//String[] arr={"hello","java","world"};
/*
* 使用asList函數(shù)將數(shù)組轉(zhuǎn)換為集合
* 由于asList函數(shù)的參數(shù)是可變參數(shù),可以接收數(shù)組
* 注意這里的泛型是String,不是String[]
* 因?yàn)閿?shù)組中保存的是引用數(shù)據(jù)類型的字符串對(duì)象,而集合是用來(lái)保存對(duì)象的
* 所以數(shù)組中的每個(gè)字符串對(duì)象數(shù)據(jù)都會(huì)放在集合中作為集合元素
*/
//List<String> list = Arrays.asList(arr);
//由于asList(T... a) 函數(shù)的參數(shù)是可變參數(shù),所以可以向如下方式傳遞數(shù)據(jù),
//其實(shí)可變參數(shù)就是個(gè)數(shù)組 而參數(shù)的類型 T和集合的泛型一樣都是String類型
//T... a ={"hello","java","world"} T[] a={"hello","java","world"};
//String[] a={"hello","java","world"};
List<String> list = Arrays.asList("hello","java","world");
//輸出list [hello, java, world]
//System.out.println(list);
//向生成的集合中添加數(shù)據(jù)
//list.add("哈哈");//不能向該集合中添加元素 否則報(bào)異常 java.lang.UnsupportedOperationException
//list.remove(1);//不能刪除該集合中的元素 否則報(bào)異常 java.lang.UnsupportedOperationException
//可以修改集合中的數(shù)據(jù),但是不能改變集合的長(zhǎng)度
list.set(0, "哈哈");
System.out.println(list);
}
}
4)如果數(shù)組中存儲(chǔ)的是基本數(shù)據(jù)類型,那么數(shù)組轉(zhuǎn)成集合,會(huì)把整個(gè)數(shù)組作為一個(gè)對(duì)象存儲(chǔ)到集合中;
代碼如下所示:
分析和步驟:
a.在上述類中的主函數(shù)中定義一個(gè)int[]數(shù)組,存儲(chǔ)幾個(gè)int類型的數(shù)據(jù);
b.使用Arrays類調(diào)用asList()函數(shù)將數(shù)組轉(zhuǎn)換為集合,并輸出結(jié)果;

說(shuō)明:輸出集合名字能夠輸出一串地址,說(shuō)明list集合中存儲(chǔ)的是一個(gè)一維數(shù)組的一串地址,也就是說(shuō)將數(shù)組整體作為集合的一個(gè)對(duì)象元素存儲(chǔ)到集合中。
上述代碼內(nèi)存圖解如下所示:

總結(jié):如果想將數(shù)組轉(zhuǎn)換為集合,讓集合操作數(shù)組中的元素建議不要將基本數(shù)據(jù)類型數(shù)組轉(zhuǎn)換為集合,可以將基本類型的數(shù)組變成對(duì)應(yīng)的包裝類類型數(shù)組在轉(zhuǎn)換為集合即可。
5)如果數(shù)組中存儲(chǔ)的是引用類型的元素,在把數(shù)組轉(zhuǎn)為集合后,該集合中存儲(chǔ)的就是數(shù)組中的所有引用類型的元素;
代碼實(shí)現(xiàn)如下所示:
分析和步驟:
1)在上述類中的主函數(shù)中定義一個(gè)String[]數(shù)組,存儲(chǔ)幾個(gè)String類型的數(shù)據(jù);
2)使用Arrays類調(diào)用asList()函數(shù)將String類型的數(shù)組轉(zhuǎn)換為集合,并輸出結(jié)果;
3)在上述類中的主函數(shù)中定義一個(gè)Integer[]數(shù)組,存儲(chǔ)幾個(gè)Integer類型的數(shù)據(jù);
4)使用Arrays類調(diào)用asList()函數(shù)將Integer類型的數(shù)組轉(zhuǎn)換為集合,并輸出結(jié)果;

說(shuō)明:Integer[]數(shù)組保存的是基本數(shù)據(jù)類型的包裝類的對(duì)象的地址,屬于引用數(shù)據(jù)類型,所以會(huì)將每一個(gè)數(shù)據(jù)保存到集合中。
上述代碼的內(nèi)存圖解如下所示:

總結(jié):
1)在開(kāi)發(fā)中不建議將基本類型的數(shù)組通過(guò)asList()函數(shù)轉(zhuǎn)換為集合,因?yàn)檗D(zhuǎn)換結(jié)果是地址,不是數(shù)組中的數(shù)據(jù),可以將基本類型的數(shù)組換成對(duì)應(yīng)的包裝類類型數(shù)組進(jìn)行轉(zhuǎn)換;
2)把數(shù)組轉(zhuǎn)成集合就是為了使用集合中的功能操作數(shù)組;
2、Date類介紹
在生活中有日期這樣的數(shù)據(jù),Java對(duì)日期這類數(shù)據(jù)也進(jìn)行了類的描述和封裝。

說(shuō)明:
1)類 Date 表示特定的瞬間,精確到毫秒。
2)Date類,在JDK1.0的時(shí)候提供了大量的函數(shù),可以進(jìn)行年月日時(shí)分秒的轉(zhuǎn)換,以及字符串和日期之間的轉(zhuǎn)換和解析。后期從JDK1.1開(kāi)始 ,年月日時(shí)分秒的轉(zhuǎn)換交給了Calendar 類 ,而字符串和日期之間的轉(zhuǎn)換交給了DateFormat類。
Date類中沒(méi)有過(guò)時(shí)的構(gòu)造函數(shù)如下:

創(chuàng)建一個(gè)Date對(duì)象,封裝就是當(dāng)前系統(tǒng)的時(shí)間信息。

把一個(gè)毫秒值封裝成Date對(duì)象。
代碼演示如下所示:
分析和步驟:
1)創(chuàng)建一個(gè)測(cè)試類DateDemo;
2)在這個(gè)類中的main函數(shù)中使用new關(guān)鍵字創(chuàng)建Date類的對(duì)象d;
3)輸出當(dāng)前的系統(tǒng)時(shí)間d;
4)根據(jù)日期對(duì)象d調(diào)用getTime()函數(shù)獲得日期對(duì)象的毫秒值time,輸出time值;
5)使用System調(diào)用currentTimeMillis()函數(shù)獲得當(dāng)前系統(tǒng)的毫秒值time2,輸出毫秒值time2;
6)把毫秒值time2作為Date類的構(gòu)造函數(shù)的參數(shù)生成日期類對(duì)象d2,并輸出d2;
package cn.xuexi.date.demo;
import java.util.Date;
/*
* Date類的演示
*/
public class DateDemo {
public static void main(String[] args) {
/*
* 創(chuàng)建一個(gè)日期對(duì)象
* 使用空參構(gòu)造函數(shù)把當(dāng)前的系統(tǒng)時(shí)間封裝成Date類的對(duì)象
*/
Date d = new Date();
//輸出當(dāng)前系統(tǒng)時(shí)間d
System.out.println(d);
//根據(jù)日期對(duì)象d獲得毫秒值
long time = d.getTime();
System.out.println(time);
//使用System類中的函數(shù)獲得當(dāng)前系統(tǒng)的毫秒值
long time2 = System.currentTimeMillis();
System.out.println(time2);
//根據(jù)毫秒值創(chuàng)建日期類的對(duì)象
Date d2 = new Date(time2);
System.out.println(d2);
}
}
Date類沒(méi)有過(guò)時(shí)的其他函數(shù):

已經(jīng)有一個(gè)Date對(duì)象,但是我們可以修改這個(gè)Date對(duì)象表示的毫秒值數(shù)據(jù)。

在Date類中必須知道怎么把毫秒值轉(zhuǎn)成Date對(duì)象,以及怎么把Date對(duì)象轉(zhuǎn)成毫秒值。
1.毫秒值轉(zhuǎn)成Date對(duì)象:構(gòu)造函數(shù) Date(long time) 使用函數(shù) setTime(long time);
2.Date對(duì)象轉(zhuǎn)成毫秒值:使用函數(shù)getTime() System.currentTimeMillis()
3、DateFormat類介紹

說(shuō)明:
1)在Java中看到文本,統(tǒng)一把這樣的數(shù)據(jù)當(dāng)做String處理;
2)DateFormat是一個(gè)抽象類,不能實(shí)例化。需要使用該類中的一個(gè)靜態(tài)方法獲取對(duì)象:

補(bǔ)充: 對(duì)于getDateInstance()函數(shù)而言,這里的日期默認(rèn)風(fēng)格是:年-月-日。yyyy-MM-dd
舉例:2015-12-27

補(bǔ)充: 對(duì)于getDateTimeInstance()函數(shù)而言,這里的日期默認(rèn)風(fēng)格是:年-月-日 時(shí):分:秒。 yyyy-MM-dd HH:mm:ss。
舉例:2015-12-27 15:42:30
3)DateFormat類:可以把日期對(duì)象轉(zhuǎn)成字符串?dāng)?shù)據(jù)(格式化),或者把字符串?dāng)?shù)據(jù)轉(zhuǎn)成日期對(duì)象(解析);
A:日期轉(zhuǎn)為字符串(格式化日期對(duì)象)

B:字符串轉(zhuǎn)為日期(解析日期格式的字符串)

案例1:DateFormat簡(jiǎn)單使用
需求:把當(dāng)前系統(tǒng)時(shí)間使用format(Date date)函數(shù)轉(zhuǎn)換為字符串(格式化功能)。
分析和步驟:
1)使用DateFormat類調(diào)用getDateInstance()函數(shù)獲得日期格式化解析的對(duì)象df;
2)創(chuàng)建當(dāng)前系統(tǒng)的日期的對(duì)象d,new Date();
3)使用日期格式化解析的對(duì)象df調(diào)用format函數(shù),把當(dāng)前系統(tǒng)日期對(duì)象d轉(zhuǎn)為字符串格式并輸出;
package cn.xuexi.date.demo;
import java.text.DateFormat;
import java.util.Date;
/*
* 需求:把當(dāng)前系統(tǒng)時(shí)間使用format函數(shù)轉(zhuǎn)換為字符串(格式化功能)。
*/
public class DateFormatDemo {
public static void main(String[] args) {
/*
* 創(chuàng)建DateFormat類的對(duì)象
* 由于DateFormat類是抽象類不能使用new關(guān)鍵字創(chuàng)建對(duì)象
* 所以只能使用DateFormat類名調(diào)用函數(shù)來(lái)獲得對(duì)象
*/
//DateFormat df = DateFormat.getDateInstance();
//System.out.println(df);//輸出內(nèi)容java.text.SimpleDateFormat@ef7951d7
DateFormat df2 = DateFormat.getDateTimeInstance();
//獲得當(dāng)前系統(tǒng)的時(shí)間
Date d = new Date();
//System.out.println(d);//輸出結(jié)果Tue Dec 27 00:27:02 GMT+08:00 2015
//使用DateFormat類的對(duì)象df調(diào)用format函數(shù)把當(dāng)前系統(tǒng)時(shí)間轉(zhuǎn)換為字符串
/*String newDate = df.format(d);
System.out.println(newDate);//輸出內(nèi)容:2015-12-27
*/
String newDate2 = df2.format(d);
System.out.println(newDate2);//輸出內(nèi)容是2015-12-27 15:42:30
}
}
案例2:把字符串對(duì)象轉(zhuǎn)為日期對(duì)象(解析功能)
- 需求:把當(dāng)前系統(tǒng)時(shí)間使用format函數(shù)轉(zhuǎn)換為字符串(格式化功能)。
需求:將一個(gè)字符串對(duì)象"2016年10月19 日15時(shí)42分30秒”解析為日期格式的對(duì)象。
說(shuō)明:getDateTimeInstance()的日期格式是:yyyy-MM-dd HH:mm:ss。
分析和步驟:
1)使用DateFormat類調(diào)用getDateTimeInstance()函數(shù)獲得日期格式化解析的對(duì)象df;
2)定義一個(gè)String類型的字符串strDate="2016年10月19 日15時(shí)42分30秒";
3)使用日期格式化解析的對(duì)象df調(diào)用parse()函數(shù)對(duì)上述字符串strDate進(jìn)行解析;
4)輸出解析后的數(shù)據(jù);

結(jié)論:在進(jìn)行解析時(shí),必須保證字符串的日期格式和要解析的對(duì)象屬于同一種格式
改進(jìn)程序:

4、SimpleDateFormat類介紹(掌握)

說(shuō)明:DateFormat類和子類SimpleDateFormat它們的主要功能就是完成日期和字符串之間的轉(zhuǎn)換。
SimpleDateFormat類有一個(gè)比較重要的構(gòu)造函數(shù)如下所示:

開(kāi)發(fā)中經(jīng)常使用上述構(gòu)造函數(shù)創(chuàng)建SimpleDateFormat對(duì)象。因?yàn)樯鲜鰳?gòu)造函數(shù)在創(chuàng)建對(duì)象的時(shí)候,可以指定樣式來(lái)對(duì)日期進(jìn)行解析或格式化。
日期和時(shí)間的常見(jiàn)模式如下所示:

說(shuō)明:
在使用SimpleDateFormat對(duì)日期數(shù)據(jù)進(jìn)行格式化或者解析的時(shí)候,指定的模式:
yy表示簡(jiǎn)寫的年份: 18年
yyyy表示全年: 2018年
M表示簡(jiǎn)寫的月份: 6月
MM表示全月:06月
d 表示日:1
dd 表示日:01號(hào)
H小時(shí): 8時(shí)
HH小時(shí):08時(shí)
m分鐘: 8分
mm分鐘:08分
s秒:9秒
ss 秒:09秒
案例:使用SimpleDateFormat對(duì)象自定義風(fēng)格解析和格式化日期對(duì)象。
需求:給定日期格式:yyyy年MM月dd日 HH時(shí)mm分ss秒。將當(dāng)前系統(tǒng)時(shí)間按照給定的日期格式進(jìn)行格式化,并輸出結(jié)果。
代碼如下所示:
分析和步驟:
1)定義一個(gè)測(cè)試類SimpleDateFormatDemo 類;
2)在這個(gè)類中的main函數(shù)中創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象 要求參數(shù)格式:yyyy年MM月dd日 HH時(shí)mm分ss秒;
3)創(chuàng)建系統(tǒng)時(shí)間對(duì)象date,輸出date;
4)將日期格式化為字符串newDate,并輸出;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
// 創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH時(shí)mm分ss秒");
//創(chuàng)建系統(tǒng)日期對(duì)象
Date date = new Date();
//輸出日期
System.out.println(date);
//將日期格式化為字符串
String newDate = sdf.format(date);
//輸出格式化后的日期
System.out.println(newDate);
}
}
需求:將字符串"2018/06/01 13時(shí)17:20秒"按照指定日期格式"yyyy/MM/dd HH時(shí)mm:ss秒"解析成為系統(tǒng)日期時(shí)間。
分析和步驟:
1)定義一個(gè)測(cè)試類SimpleDateFormatDemo1 類;
2)在這個(gè)類中的main函數(shù)中創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象sdf, 要求參數(shù)格式:yyyy/MM/dd HH時(shí)mm:ss秒;
3)定義一個(gè)字符串s用來(lái)保存日期:"2018/06/01 13時(shí)17:20秒";
4)使用日期格式化對(duì)象sdf調(diào)用parse()函數(shù)將字符串s解析成系統(tǒng)日期時(shí)間date,并輸出轉(zhuǎn)換后的日期date;
package cn.xuexi.date.demo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 案例:使用SimpleDateFormat對(duì)象自定義風(fēng)格解析和格式化日期對(duì)象
*/
public class SimpleDateFormatDemo {
public static void main(String[] args) {
//將字符串解析成為系統(tǒng)日期時(shí)間
//定義一個(gè)字符串
String strDate="2018/06/01 13時(shí)17:20秒";
// 創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd HH時(shí)mm:ss秒");
//使用sdf2調(diào)用parse()函數(shù)將上述字符串strDate解析成系統(tǒng)日期時(shí)間
try {
Date date2 = sdf2.parse(strDate);
System.out.println(date2);
} catch (Exception e) {
System.out.println("日期格式不對(duì),應(yīng)該是:yyyy/MM/dd HH時(shí)mm:ss秒");
}
}
}
練習(xí):"2014-08-09 09:09:09" 與 "2026年08/01 10:10:10" 相差多少個(gè)月。
分析和思路:
2個(gè)字符串形式表示的日期數(shù)據(jù),要計(jì)算時(shí)間差,首先就需要獲取到當(dāng)前字符串表示的Date對(duì)象,然后通過(guò)Date對(duì)象在獲取日期對(duì)象的毫秒值。
毫秒值是long型的數(shù)據(jù),就可以使用算術(shù)運(yùn)算計(jì)算差值。
分析和步驟:
1)創(chuàng)建一個(gè)SimpleDateFormatTest 測(cè)試類;
2)在這個(gè)類中的main函數(shù)中創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象
sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
3)在創(chuàng)建一個(gè)自定義的格式化解析器對(duì)象
sdf2=new SimpleDateFormat("yyyy年MM/dd HH:mm:ss");
4)定義兩個(gè)字符串s1和s2分別保存"2014-08-09 09:09:09"和"2026年08/01 10:10:10";
5)使用sdf和sdf2調(diào)用parse()函數(shù)將字符串解析成Date類的對(duì)象date1和date2;
6)使用date1和date2對(duì)象調(diào)用getTime()函數(shù)獲取毫秒值t1和t2;
7)使用兩個(gè)毫秒值t1和t2相互相減,然后進(jìn)行算數(shù)運(yùn)算,得到結(jié)果并輸出即可;
package cn.xuexi.date.demo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 練習(xí):"2014-08-09 09:09:09" 與 "2026年08/01 10:10:10" 相差多少月。
*/
public class SimpleDateFormatTest {
public static void main(String[] args) {
//創(chuàng)建格式化解析器對(duì)象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM/dd HH:mm:ss");
//定義兩個(gè)字符串變量來(lái)保存日期
String s1="2014-08-09 09:09:09";
String s2="2026年08/01 10:10:10";
//使用格式化解析器對(duì)象將上述字符串s1和s2解析成Date時(shí)間對(duì)象
try {
Date date1 = sdf.parse(s1);
Date date2 = sdf2.parse(s2);
//根據(jù)時(shí)間對(duì)象獲得毫秒值
long time1 = date1.getTime();
long time2 = date2.getTime();
/*
* 兩個(gè)時(shí)間相減 結(jié)果有可能為負(fù)數(shù),所以我們可以讓無(wú)論是正數(shù)還是負(fù)數(shù)都變成正數(shù)
* Math.abs(time1-time2) 表示毫秒值相減的結(jié)果,而我們需要得知相差的月份
* 所以得把毫秒值計(jì)算為月份
*/
//long temp=Math.abs(time1-time2)/1000/60/60/24/365;//相差年份
long temp=Math.abs(time1-time2)/1000/60/60/24/30;//相差月份
System.out.println(temp);
} catch (Exception e) {
System.out.println("時(shí)間格式不對(duì)");
}
}
}
5、Calendar類介紹(掌握)

說(shuō)明:
1)Calendar類是一個(gè)抽象類,不能實(shí)例化對(duì)象。(需要通過(guò)方法獲取Calendar對(duì)象)

2)Calendar類屬于一個(gè)日歷類,記錄了一些生活中常用的日歷字段,比如年、月、日、時(shí)、分、秒等一些日期與時(shí)間的相關(guān)信息。
案例:Calendar類的使用。
分析和步驟:
1)創(chuàng)建一個(gè)CalendarDemo測(cè)試類;
2)在這個(gè)測(cè)試類的main函數(shù)中通過(guò)Calendar類調(diào)用getInstance()函數(shù)獲得日歷對(duì)象c;
3)輸出日歷對(duì)象c;

運(yùn)行結(jié)果:

注意:
1)在計(jì)算機(jī)中月份是從零開(kāi)始計(jì)算的。也就是說(shuō)數(shù)字0 表示1月,數(shù)字1表示2月,以此類推數(shù)字11表示12月。12表示下一年的1月;
2)一周中周日是第一天;
3)Calendar類中輸出結(jié)果是一些key-value對(duì)應(yīng)的信息。其實(shí)在Calendar對(duì)象內(nèi)部維護(hù)了一個(gè)Map集合,把當(dāng)前系統(tǒng)日期與時(shí)間上的所有信息全部使用key=value的形式保存在Calendar這個(gè)類中。
問(wèn)題:既然將當(dāng)前系統(tǒng)日期與時(shí)間上的所有信息全部存在了一個(gè)Map集合中,那么當(dāng)我們需要具體的什么信息時(shí),是否可以直接通過(guò)這個(gè)Calendar類來(lái)獲取,或者是否可以直接通過(guò)指定對(duì)應(yīng)的key,拿到當(dāng)前key對(duì)應(yīng)的value值呢?
答案是可以的。
使用Calendar類中的get(int field)函數(shù)就可以獲取Calendar對(duì)象中描述當(dāng)前時(shí)間數(shù)據(jù)。需要根據(jù)指定的key來(lái)獲取對(duì)應(yīng)的value。

注意:Calendar類是用來(lái)保存某個(gè)時(shí)間點(diǎn)上的所有和時(shí)間相關(guān)的數(shù)據(jù)。然后我們就可以通過(guò)Calendar類中的靜態(tài)成員變量作為key值(或者說(shuō)作為get()函數(shù)的參數(shù))來(lái)獲取其中的任何一個(gè)value數(shù)據(jù)。
案例:獲取Calendar對(duì)象中的日歷字段。(想要輸出” xxxx年xx月xx日”)
分析和步驟:
1)創(chuàng)建一個(gè)CalendarDemo1測(cè)試類;
2)在這個(gè)測(cè)試類的main函數(shù)中先創(chuàng)建Date類的對(duì)象d,通過(guò)對(duì)象d獲得當(dāng)前年、月、日,但是Date類中的函數(shù)都過(guò)期了;
3)通過(guò)Calendar類調(diào)用getInstance()函數(shù)獲得日歷對(duì)象c;
4)通過(guò)c對(duì)象調(diào)用get()函數(shù),Calendar.YEAR、Calendar.MONTH、Calendar.DAY_OF_MONTH依次作為函數(shù)的參數(shù)來(lái)獲得年、月(月份是從0開(kāi)始的到11,所以獲得月份需要+1)、日;
5)輸出獲得的年、月、日;
代碼如下所示:
package cn.xuexi.date.demo;
import java.util.Calendar;
import java.util.Date;
/*
* 案例:獲取Calendar對(duì)象中的日歷字段。(想要輸出” xxxx年-xx月-xx日”)
*/
public class CalendarDemo1 {
public static void main(String[] args) {
// 創(chuàng)建時(shí)間日期類對(duì)象
/*Date d = new Date();
//獲得系統(tǒng)的年月日
int year = d.getYear();//年 當(dāng)前系統(tǒng)時(shí)間減去1900
int month = d.getMonth();//月 月份從0~11
int day = d.getDate();//日 表示獲得一個(gè)月中的某一天
//int day1 = d.getDay();//日 表示獲得一周中的某一天 0 表示星期日 1 表示星期一 2表示星期二
//輸出Date類獲取的年月日
System.out.println(year+"年"+month+"月"+day+"日");*/
//Date日期類已經(jīng)過(guò)期了,被Calendar日歷類所取代了
//創(chuàng)建日歷類Calendar類的對(duì)象
Calendar c = Calendar.getInstance();//使用靜態(tài)方法獲取日歷對(duì)象
//使用日歷對(duì)象c調(diào)用get函數(shù)獲得年份
int year = c.get(Calendar.YEAR);//年
int month = c.get(Calendar.MONTH)+1;//月份 從0開(kāi)始到11
int day = c.get(Calendar.DAY_OF_MONTH);//一個(gè)月中的某一天
System.out.println(year+"年"+month+"月"+day+"日");
}
}
3)Calendar類的set()和add()函數(shù);

說(shuō)明:給當(dāng)前Calendar對(duì)象中的某個(gè)key設(shè)置value值。

說(shuō)明:是在當(dāng)前的時(shí)間點(diǎn)上添加某些時(shí)間。field 表示Calendar類中的成員變量,集合中key值。amount 表示當(dāng)前指定的數(shù)據(jù),這個(gè)數(shù)據(jù)可以是正數(shù),也可以是負(fù)數(shù)。正數(shù)代表著在當(dāng)前時(shí)間上加上amount 變量,負(fù)數(shù)代表著在當(dāng)前時(shí)間上減去amount 變量。
案例:Calendar類的set方法和add方法
分析和步驟:
1)創(chuàng)建一個(gè)CalendarDemo2測(cè)試類;
2)在這個(gè)測(cè)試類的main函數(shù)中通過(guò)Calendar類調(diào)用getInstance()函數(shù)獲得日歷對(duì)象c;
3)使用對(duì)象c調(diào)用set()函數(shù),并且Calendar.YEAR作為key,2011作為value來(lái)修改日歷字段中的年份;
4)使用對(duì)象c調(diào)用set()函數(shù)來(lái)設(shè)置日歷對(duì)象中的年月日;
5)使用對(duì)象c調(diào)用add()函數(shù),Calendar.MONTH作為key,1作為value在當(dāng)前日歷對(duì)象的基礎(chǔ)上增加一個(gè)月;
6)使用對(duì)象c調(diào)用add()函數(shù),Calendar.DAY_OF_MONTH作為key,-1作為value在當(dāng)前日歷對(duì)象的基礎(chǔ)上減少一天;
7)分別獲得年月日,并輸出獲得的年、月、日;
package cn.xuexi.date.demo;
import java.util.Calendar;
/*
* 案例:Calendar類的set方法和add方法
*/
public class CalendarDemo2 {
public static void main(String[] args) {
// 使用靜態(tài)方法獲得日歷類對(duì)象
Calendar c = Calendar.getInstance();
//通過(guò)對(duì)象c調(diào)用set函數(shù)更改年
//c.set(Calendar.YEAR, 2013);
//更改日歷對(duì)象中的年月日
//c.set(2012, 1, 1);
//System.out.println(c);
/*
* 這里的月份13超出了月份的范圍11
* 所以當(dāng)月份或者天數(shù)超出了所屬字段范圍后,會(huì)修改前面的日歷字段
*/
//這里的月份13超出了月份的范圍11 結(jié)果是2013年2月1日 月份超出了范圍,修改年
//c.set(2012, 13, 1);//2013年2月1日
//這里的天數(shù)29超出了天數(shù)的范圍28 結(jié)果是2017年3月1日 天數(shù)超出了范圍,修改月
c.set(2017, 1, 29);//2017年3月1日
//使用日歷對(duì)象c調(diào)用add函數(shù)修改日歷中的數(shù)據(jù)
//c.add(Calendar.MONTH, 1);//在當(dāng)前月份上加1個(gè)月
c.add(Calendar.DAY_OF_MONTH, -1);//在當(dāng)前月的天數(shù)上減1
//獲取年月日
int year=c.get(Calendar.YEAR);//年
int month=c.get(Calendar.MONTH)+1;//月
int day=c.get(Calendar.DAY_OF_MONTH);//日
//輸出
System.out.println(year+"年"+month+"月"+day+"日");
}
}
注意:
在使用set或add方法時(shí),如果設(shè)置的日歷字段超出當(dāng)前字段所屬范圍后,就會(huì)修改前面日歷字段的值:
1)月份超出了范圍,修改年;
2)天數(shù)超出了范圍,修改月;
3)如果日歷字段設(shè)置的值為負(fù)數(shù):就在當(dāng)前日歷字段的基礎(chǔ)上減;
4)如果日歷字段設(shè)置的值為正數(shù):就在當(dāng)前日歷字段的基礎(chǔ)上加;
面試題:
需求:使用最有效的方式獲取指定年份中2月的最大天數(shù)。
分析:一年中的二月份的天數(shù)有29天(閏年)或者28天(平年),也就是說(shuō)2月最大的天數(shù)要么是29,要么是28.
無(wú)論是29天還是28天,后一天肯定是3月1號(hào),那么我們可以先獲得一年中的3月1號(hào),然后在1號(hào)的基礎(chǔ)上減1,這樣就獲得了2月份的最大天數(shù)了。
分析和步驟:
1)創(chuàng)建CalendarTest類;
2)在CalendarTest類中使用Calendar調(diào)用getInstance()函數(shù)獲得日歷類的對(duì)象c;
3)使用日歷類對(duì)象c調(diào)用set()函數(shù)把時(shí)間設(shè)置成某一年的3月1日;
4)使用日歷類對(duì)象c調(diào)用add()函數(shù)把月中的天數(shù)-1;
5)日歷類對(duì)象c調(diào)用get()函數(shù)獲得年、月(月數(shù)+1)、日,并打??;
package cn.xuexi.date.demo;
import java.util.Calendar;
/*
* 需求:使用最有效的方式獲取指定年份中2月的最大天數(shù)。
*/
public class CalendarTest {
public static void main(String[] args) {
// 根據(jù)靜態(tài)方法獲取日歷對(duì)象
Calendar c = Calendar.getInstance();
//使用日歷對(duì)象c調(diào)用set函數(shù)把日期設(shè)置到某一年的3月1號(hào)
for (int year = 1000; year < 2020; year++) {
//設(shè)置某一年的3月1日
c.set(year, 2, 1);//計(jì)算機(jī)中的月份0~11
//三月份天數(shù)倒退一天,就是減少一天
c.add(Calendar.DAY_OF_MONTH, -1);
// 獲取年月日
int year2 = c.get(Calendar.YEAR);// 年
int month = c.get(Calendar.MONTH) + 1;// 月
int day = c.get(Calendar.DAY_OF_MONTH);// 日
// 輸出
System.out.println(year2 + "年" + month + "月" + day + "日");
}
}
}