2016-2017-2 《Java程序設計》第七週學習總結

20155313 2016-2017-2 《Java程序設計》第七週學習總結

第十二章 Lambda

12.1認識Lambda語法

12.1.1Lambda語法概覽

  • java中引入了Lambda的同時,與現有API維持兼容性是主要考慮之一。
  • 方法參考的特性,在重用現有API上扮演了重要角色。
  • 重用現有方法操做,可避免處處寫下Lambda表達式。
  • 方法參考不只避免了重複撰寫Lambda表達式,也可讓程序代碼更清楚。

12.1.2Lambda表達式與函數接口

  • 在只有Lambda表達式的狀況下,參數的類型必須寫出來,若是有目標類型的話,在編譯程序可推斷出類型的狀況下,就能夠不寫出Lambda表達式的參數類型。
  • Lambda表達式自己是中性的,不表明任何類型的實例,一樣的Lambda表達式,可用來表示不一樣目標類型的對象操做。
  • JDK8Lambda並無導入新類型來做爲Lambda表達式的類型,而是就現有的interface語法來定義函數接口,做爲Lambda表達式的目標類型。
  • 若是接口使用了@FunctionalInterface來標註,而自己並不是函數接口的話,就會引起編譯錯誤。

12.1.3Lambda趕上this與final

  • Lambda表達式並非匿名類的語法蜜糖。
  • Lambda表達式中this的參考對象以及toString()的接受者,是來自Lambda的周圍環境,也就是看Lambda表達式是在哪一個名稱範疇,就能參考該範疇內的名稱,像是變量或方法。
  • JDK中,若是變量自己等效於final局部變量,也就是說,若是變量不會再匿名類中有從新指定的動做,就能夠不用加上final關鍵詞。
  • 若是Lambda表達式中捕獲的局部變量自己等效於final局部變量,能夠不用在局部變量上加上final
  • lambda表達式中不能夠改變被捕獲的局部變量值。

12.1.4方法與構造函數參考

  • Lambda表達式只是定義函數接口操做的一種方式,除此以外,只要靜態方法的方法簽署中,參數與返回值定義相同,也可使用靜態方法來定義函數接口操做。

12.1.5接口默認方法

  • 除了參考靜態方法做爲函數接口操做以外,還能夠參考特定對象的實例方法。
  • 函數接口操做也能夠參考類上定義的非靜態方法,函數接口會試圖用第一個參數方法接受者,而以後的參數依次做爲被參考的非靜態方法的參數

13.1認識時間與日期

13.1.1時間的度量

1.格林威治標準時間(GMT):常被不嚴謹地當成是UTC時間,現已不做爲標準時間使用。html

2.世界時(UT):在1972年引入UTC以前,GMT與UT是相同的java

3.國際原子時(TAI):秒的單位定義是基於TAI,也就是銫原子輻射振動次數。git

4.世界協調時間(UTC):UTC考慮了地球自轉愈來愈慢而有閏秒修正,確保UTC與UT相差不會超過0.9秒。express

5.Unix時間:不考慮閏秒修正,用以表達時間軸上某一瞬間api

6.epoch:某個特定時代的開始,用以表達時間軸上某一瞬間ide

13.1.2年曆簡介

1.儒略曆:修正了羅馬歷隔三年設置一閏年的錯誤,改採四年一閏。函數

2.格里高利曆:將儒略曆1582年10月4號星期四的隔天,訂爲格里高利曆1582年10月15日星期五。學習

3.ISO 8601標準,採用統一的數據格式例如:yyyy-mm-ddTHHH:MM:SS.SSS。this

13.1.3認識時區

  • 每一個地區的標準時間各不相同,涉及到地理、法律、經濟、社會、政治等問題。.net

  • 考慮了UTC偏移的時間表示上,一般會標識Z符號。

  • 有些高緯度國家,夏季、冬季日照時間差別很大,實施日光節約時間。

13.2認識Date與Calendar

13.2.1時間軸上瞬間的Date

eg:使用Date實例來取得系統時間描述。
運行結果

13.2.2格式化時間日期的DateFormate

  • DateFormat是個抽象類,其操做類是java.text.SimpleDateFormat,你能夠直接構建SimpleDateFormat實例,或是使用DateFormat的getDateInstance()、getTimeInstance()、getDateTimeInstance等靜態方法,用較簡便方式按不一樣需求取得SimpleDateFormat實例。
    eg:如何經過DateFormat的各類靜態方法進行格式化。

eg:直接構建SimpleDateFormat的好處是,可以使用模式字符串自定義格式。

eg:SimpleDateFormat有一個parse()方法,能夠按構建SimpleDateFormat時指定的格式,將指定的字符串剖析爲Date實例,

13.2.3處理時間日期的Calendar

  • Date如今建議做爲時間軸上的瞬間表明,要格式化時間日期則經過DateFormat,若是想要取得某個時間日期信息,或者是對時間日期進行操做,可使用Calendar實例。

  • Calendar是個抽象類,java.util.GregorianCalendar是其子類,操做了儒略曆與格里高利曆的混合歷,經過Calendar的getInstance()取得的Calendar實例,默認就是取得GregorianCalendar實例。

eg:

Calendar calendar = Calendar.getInstance();

取得Calendar實例後,可使用getTime()取得Data實例,若是想要取得年月日等日期數字時段,可使用get()方法並指定Calendar上的數字段枚舉常數。
eg:想取得年、月、日字段。

out.println(calendar.get(Calendar.YEAR));
out.println(calendar.get(Calendar.MONTH));
out.println(calendar.get(Calendar.DATE));

若是你要設定時間日期等字段,不要對Date設定,應該使用Calendar,一樣地,月份的部分請使用枚舉常數設定。
eg:

Calendar calendar = Calendar.getInstace();
calendar.set(2016,Calendar.APRIL,16);   // 2016/04/16
out.println(calendar.get(Calendar.YEAR));   // 2016  
out.println(calendar.get(Calendar.MOUNTH)); //Calendar.APRIL取值3
out.println(calendar.get(Calendar.DATE));   //16

在取得一個Calendar的實例後,可使用add()方法,來改變Calendar的時間。
eg:

calendar.add(Calendar.MONTH,1);  //Calendar時間加1個月
calendar.add(Calendar.HOUR,3);   //Calendar時間加3小時
calendar.add(Calendar.YEAR,-2);  //Calendar時間減2年
calendar.add(Calendar.DATE,3);   //Calendar時間加3天

若是打算只針對日期中某個字段加減,則可使用roll()方法。
eg:

calendar.roll(Calendar.DATE,1);  //只對日字段加1

想比較兩個Calendar的時間日期前後,可使用after()或before()方法。
eg:使用Calendar計算用戶的歲數。

13.2.4設定TimeZone

使用Calendar時若沒有使用時區信息,則會使用默認時區。
eg:可使用java.util.TimeZone的getDefault()來取得默認時區信息。

Calendar在調用getInstance()時,能夠指定Timezone,若是已經取得Calendar實例,也能夠經過setTimeZone()方法設定TimeZone。

eg:想知道如今哥本哈根的時間,並指定TimeZone爲北京。

13.3JDK8新時間日期API

13.3.1機器時間觀點的API

因爲臺灣時區已經不實施日光節約一段時間了,許多開發者並不知道過去有過日光節約時間,在取得Date實例後,被名稱Date誤導他們表明日期,因此不該該使用Data實例來得知人類觀點的時間信息,Date實例只表明機器觀點的時間信息,真正可靠的信息只有內含epoch毫秒數。

同時也可使用Instant的靜態方法now()取得表明Java epoch毫秒數的Instant實例。

在新舊API兼容上,若是取得了Date實例,而想要改用Instant,則能夠調用Date實例的toInstant()方法來取得,若是你有個Instant實例,可使用Instant的靜態方法from()轉爲Date。

13.3.2人類時間觀點的API

1.LocalDateTime、LocalDate和LocalTime

LocalDateTime:包括日期與時間

LocalDate:只有日期,若是設定不存在的日期,會拋出DateTimeException

LocalTime:只有時間

這些類基於ISO 8601年曆系統,是不具時區的時間與日期定義。

對於LocalDateTime.of,因爲沒有時區信息,程序無從判斷這個時間是否不存在,就不會拋出DateTimeException

2.ZonedDateTime、OffsetdateTime

eg:若是你的時間日期須要帶有時區,能夠基於LocalDateTime、LocalDate、LocalTime等來補充缺乏的信息。

運行結果

3.Year、YearMonth、Month、MonthDay

eg:若是想要取得表明月份的數字,不要使用oridinal()方法,由於oridinal()是enum在定義時的順序,從0開始,想要取得表明月份的數要經過getValue()方法(調整了格式,使其對齊)。

運行結果

13.3.3對時間的運算

1.TemporalAmount

ofPattern()是java.time.format.DateTimeFormatter的靜態方法,能夠查看API文件瞭解格式化的方式。

對於時間計量,新時間與日期API以類Duration來定義,可用於計量天、時、分、秒的時間差,精度調整能夠達納秒等級,而秒的最大值能夠是long類型可保存值。

對於年、月、星期、日的日期差,使用Period類定義。

plus()方法能夠接受Duration實例來計算

eg:使用新時間與日期API改寫HowOld範例。

2.TemporalUnit

plus()方法另外一重載版本,接受java.time.temporal.TemporalUnit實例,java.time.temporal.ChronoUnit是TemporalUnit實做類,使用enum實做。

TemporalUnit定義了between()等方法。

3.Temporal

相對於plus(),也有兩個重載兩個重載版本的minus():

plus(TemporalAmount amount)

plus(long amountToAdd,TemporalUnit unit)

minus(TemporalAmount amount)

minus(long amountToSubtract,TemporalUnit unit)

4.TemporalAccessor

TemporalAccessor定義了只讀的時間對象讀取操做,實際上Temporal是TemporalAccessor子接口,增長了對時間的處理操做,像是plus()、minus()、with()等方法。
13.3.4年曆系統設計

java.time套件中的類在須要實行年曆系統時都是採用單一的ISO8601年曆系統。如須要其餘年曆系統,則須要明確實行java.time.chrono中等操做了java.time.chrono.Chronology接口的類。


教材學習中的問題和解決過程

問題1:如何用lambda實現集合map的試用?

回答1:

集合的map的方法使用

public class test {  
  
    public static void main(String[] args) {  
  
        List<Integer> list=Arrays.asList(1,4,5);  
          
        list.stream()  
            .map(name->name+1)  
            .forEach(System.out::println);  
    }  
}

問題2:如何用lambda實現集合filter的試用?

回答2:

集合的filter方法使用

public class test {  
  
    public static void main(String[] args) {  
  
        List<Integer> list=Arrays.asList(1,4,5);  
          
        list.stream()  
            .filter(name->name%2==0)  
            .forEach(System.out::println);  
    }  
}

代碼調試中的問題和解決過程

問題1:如何使用lambda簡化下列排序代碼?

String[] players = {"Rafael Nadal", "Novak Djokovic",   
    "Stanislas Wawrinka", "David Ferrer",  
    "Roger Federer", "Andy Murray",  
    "Tomas Berdych", "Juan Martin Del Potro",  
    "Richard Gasquet", "John Isner"};  
   
// 1.1 使用匿名內部類根據 name 排序 players  
Arrays.sort(players, new Comparator<String>() {  
    @Override  
    public int compare(String s1, String s2) {  
        return (s1.compareTo(s2));  
    }  
});

回答1:使用lambdas,能夠經過下面的代碼實現一樣的功能:

// 1.2 使用 lambda expression 排序 players  
Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));  
Arrays.sort(players, sortByName);  
  
// 1.3 也能夠採用以下形式:  
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));

代碼託管

  • 代碼提交過程截圖:
    • 運行 git log --pretty=format:"%h - %an, %cd : %s" 並截圖
  • 代碼量截圖:
    • 運行 find src -name "*.java" | xargs cat | grep -v ^$ | wc -l 並截圖


結對及互評

點評過的同窗博客和代碼

20155201

20155322

20155236

20155316


學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 50/100 1/2 10/20
第二週 150/200 1/2 20/30
第三週 168/200 1/2 15/20
第四周 300/500 1/2 20/20
第五週 885/1000 1/2 30/30
第六週 1211/1000 1/3 30/30
第七週 597/1000 2/3 30/40

參考資料

《Java學習筆記(第8版)》學習指導

2016-2017-2 《Java程序設計》教學進程

相關文章
相關標籤/搜索