20145226 《Java程序设计》第七周学习总结

教材学习内容总结

学习目标

· 了解Lambda语法

· 了解方法引用

· 了解Fucntional与Stream API

· 掌握Date与Calendar的应用

· 会使用JDK8新的时间API

第十二章 Lambda

12.1 认识Lambda语法

1.首先掌握Lambda的语法,其中Lambda去重复信息,遵守DRY(don't repeat yourself 不要重复自己)的原则,使得代码更加简洁。例如下面代码所示:


Comparator<String>byLength = (String name1,String name2)->name1.length() - name2.length();



在只有Lambda表达式的情况下,参数的类型必须写出来,如果有目标类型的话,在编译程序可推断出类型的情况下,就可以不写出Lambda表达式的参数类型。在本例中,编译器可以byLength变量的声明类型来推测name1和name2的类型为String类型,也可进一步将代码简化。如下所示:


Comparator<String>byLength = (name1,name2)->name1.length() - name2.length();



Lambda表示式本身是中性的,不代表任何型态的实例,同样的Lambda表示式,可用来表示不同目标型态的对象操作,例如上面的Lambda表达式可以用来表达另一种目标形态的对象操作:


Shu<String,Integer> shuzi = (name1,name2)->name1.length() - name2.length();



2.Lambda表达式和函数接口(Functional Interface):

 Lambda并没有导入新类型来作为Lambda表达式的类型,而是就现有的interface语法来定义函数接口,作为Lambda表达式的目标类型。并且Lambda表达式只关心方法签署上的参数与返回定义,但忽略方法名称。在JDK8中引入新标注@FunctionalInterface。例如:

@FunctionalInterface

public iterface Func<P,R>{

    R apply(P p);

}



注:若某个接口使用了@FunctionalInterface来标注,但其本身并非函数接口的话,就会引发编译错误。

3.方法与构造函数参考:

 可重用现有API的已有方法,避免重复编写对应的Lambda表达式,同时也能让程序的代码更加清晰。

4.接口默认方法(Default Method):

 在接口定义时可以加入默认方法(Default methods),在默认方法中不能使用数据成员,因为接口本身不能定义数据成员。

12.2 Functional与Stream API

1.使用Optional取代null:
     null的最根本值进行检查。含糊不清。在jdk8中调用方法时若返回Optional类型表示它可能包含也可能不包含值,需要对包的值进行检查。在Optional没有包含值的情况下会抛出NoSuchElementException。也可调用Optional的ofNullable()来衔接程式库传回null的方法。

2.标准的API的函数接口:
(1)Consumer函数接口:接受一个自变量,处理后不返回值时,就使用Consumer接口。主要是接受单一对象实例作为自变量,这行为就像是直接消耗了自变量,若真的有结果产生,会以副作用(Side Effect)形式显示,例如改变某对象状态或是直接进行输入输出行为。
(2)Function函数接口:接受一个自变量,然后以该自变量进行计算后传回结果,就可以使用Function接口。这个行为就像是数学函数,例如y=f(x)是根据x的值来计算y的值。
(3)Predicate函数接口:接受一个自变量,然后只传回boolean值,也就是根据传入的自变量直接论断真假的行为,就可以使用Predicate接口。
(4)Supplier函数接口:不接受任何自变量,然后传回值,就可以使用Supplier接口。既然不接受自变量,则返回来源有几个可能性,例如提供容器、固定值、某时间某事物的状态等等。

3.使用Stream进行管道操作:
一个管道主要包含来源、零到多个中间操作和一个最终操作几个部分组成。

第十三章 时间与日期
13.1 认识时间与日期

1.时间的度量 -- 时间基准

就目前来说,即使标注为格林威治标准时间(GMT时间),实际上谈到时间指的是UTC时间(世界时)。秒的单位定义是基于TAI(国际原子时),也就是铯原子辐射振动次数。UTC考虑了地球自转越来越慢而有闰秒修正,确保UTC与UT相差不会超过0.9秒。Unix时间是1970年1月1日00:00:00 为起点而经过的秒数,不考虑闰秒。

2.年历简介:
儒略历:修正了罗马历隔三年设置一闰年的错误,改采四年一闰。
格里高利历:改革了儒略历。
ISO 8601标准:并非年历系统,而是时间日期表示方法的标准,用以统一时间日期的数据交换格式。

3.认识时区:牵涉到地理、法律、经济、社会甚至政治等问题,所以每个地区的标准时间各不相同。

13.2 认识Date与Calender

1.时间轴上瞬间的Date:
若想要取得系统时间,方法之一是使用System.currentTimeMillis()方法,返回的是long类型整数,代表1970年1月1日0时0分0秒0毫秒至今经过的毫秒数。有人会使用Date实例来取得系统时间描述,不过Date也是偏向机器的时间观点。例如DateDemo.java的运行结果如下:

PS:本人最近换了电脑,所以截图有变化。

其中Date有两个构造函数可以使用,一个可使用epoch毫秒数构建,另一个为无自变量构造函数,内部亦是使用System.currentTimeMillis()取得epoch毫秒数,调用getTime()可取得内部保存的epoch毫秒数值。

因Date实例的时区无法变换,不建议使用toString()来得知年月日等字段信息,换句话说有关字符串时间格式的处理,不再是Date的职责。

2.格式化时间日期DateFormat:
DateFormat是个抽象类,其操作类是java.text.SimpleDateFormat,你可以直接构建SimpleDateFormat实例,或是使用DateFormat的getDateInstance()、getTimeInstance()、getDateTimeInstance等静态方法,用较简便方式按不同需求取得SimpleDateFormat实例。DateFormat的各种静态方法进行格式化如下所示:

import static java.lang.System.out;
import static java.text.DateFormat.*;
import java.util.Date;

public class DateFormatDemo {
	public static void main(String[] args) {
        Date date = new Date();
        dateInstanceDemo(date);
        timeInstanceDemo(date);
        dateTimeInstanceDemo(date);
    }
    
    static void dateInstanceDemo(Date date) {
        out.println("getDateInstance() demo");
        out.printf("\tSHORT: %s%n", getDateInstance(LONG).format(date));
        out.printf("\tSHORT: %s%n", getDateInstance(SHORT).format(date));
    }

    static void timeInstanceDemo(Date date) {
    	out.println("getTimeInstance() demo");
    	out.printf("\tLONG: %s%n", getTimeInstance(LONG).format(date));
    	out.printf("\tMEDIUM: %s%n", getTimeInstance(MEDIUM).format(date));
    	out.printf("\tSHORT: %s%n",getTimeInstance(SHORT).format(date));
    }
    
    static void dateTimeInstanceDemo(Date date) {
    	out.println("getDateTimeInstance() demo");
    	out.printf("\tLONG: %s%n", 
           getDateTimeInstance(LONG, LONG).format(date));
    	out.printf("\tMEDIUM: %s%n",
           getDateTimeInstance(SHORT, MEDIUM).format(date));
    	out.printf("\tSHORT: %s%n",
           getDateTimeInstance(SHORT, SHORT).format(date));
    }
}


DateFormatDemo.java的运行结果如下所示:

3.直接构建SimpleDateFormat的好处是,可使用模式字符串自定义格式,例:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CurrentTime {
	public static void main(String[] args) {
        DateFormat dateFormat = new SimpleDateFormat(
                args.length == 0 ? "EE-MM-dd-yyyy" : args[0]);  
        System.out.println(dateFormat.format(new Date())); 
    }
}

CurrentTime.java的运行结果如下所示:

SimpleDateFormat有一个parse()方法,可以按构建SimpleDateFormat时指定的格式,将指定的字符串剖析为Date实例,例:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class HowOld {
	public static void main(String[] args) throws Exception {
        System.out.print("请输入出生年月日(yyyy-mm-dd):");
        DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
        Date birthDate = dateFormat.parse(new Scanner(System.in).nextLine());
        Date currentDate = new Date();
        long life = currentDate.getTime() - birthDate.getTime();
        System.out.println("你今年的岁数为:" +
                (life / (365 * 24 * 60 * 60 * 1000L)));
    }
}


其运行结果如下所示:

4.处理时间日期的Calendar
Date现在建议作为时间轴上的瞬时代表,要格式化时使用DateFormat。但是如果要取得某个时间日期信息,或者对时间日期进行操作时则使用Calendar实例。

可通过Calendar的getInstance()取得的Calendar实例,默认就是取得GregorianCalendar实例,例如:
Calendar calendar = Calendar.getInstance();

取得Calendar实例后,可以使用getTime()取得Date实例,如果想要取得年月日等日期时间字段,可以使用get()方法指定Calender上的字段枚举常数,例如:

out.println(calendar.get(Calendar.YEAR));  //年
out.println(calendar.get(Calendar.MOUNTH));  //月
out.println(calendar.get(Calendar.DATE));  //日

如果你要设定时间日期等字段,不要对Date设定,应该使用out.println(calendar.get(Calendar.YEAR));,同样地,月份的部分请使用枚举常数设定,如下所示:

Calendar calendar = Calendar.getInstace();
calendar.set(2017,Calendar.FEBRUARY,08);    //2017/2/8
out.println(calendar.get(Calendar.YEAR));     //2017
out.println(calendar.get(Calendar.MOUNTH));   //Calendar.MAY的值1
out.println(calendar.get(Calendar.DATE));     //08

在取得一个Calendar的实例后,可以使用add()方法,来改变Calendar的时间,具体如下所示:

calendar.add(Calendar.MONTH,2);  //Calendar时间加两个月
calendar.add(Calendar.HOUR,-6);   //Calendar时间减六小时
calendar.add(Calendar.YEAR,1);  //Calendar时间加一年
calendar.add(Calendar.DATE,-8);   //Calendar时间减八天

如果打算只针对日期中某个字段加减,则可以使用roll()方法,具体如下:

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

若是要比较两个Calendar的时间日期先后,可以使用after()或before()方法。

5.设定TimeZone:

可使用java.util.TimeZone的getDefault()来取得默认时区信息。运行结果如下所示:

如果要取得指定时区的TimeZone实例可使用ID字符串,具体如下所示:
TimeZone taipeiTz = TimeZone.getTimeZone("Asia/Taipei");  //台北时间
TimeZone copenhagenTz = TimeZone.getTimeZone("Europe/Copenhagen");  //中欧时间

可用ID可使用TimeZone.getAvailableIDs()来取得,它会返回String[]。Calendar在调用getInstance()时,可以指定TimeZone,如果已经取得Calendar实例,也可以通过setImeZone()方法设定TimeZone。

13.3 JDK8新时间日期API

1.机器时间观点的API:
Date名称看来像是人类的时间概念,实际却是机器的时间概念,混淆机器与人类时间观点会引发的问题之一像是日光节约时间。对于机器相关的时间概念,设计了Instant类,用于表示Java epoch之后某个时间点经历的毫秒数。可以使用now()来获取代表Java epoch毫秒数的Instance实例;ofEpochMill()来指定Java epoch毫秒数;ofEpochSecond()来指定秒数,以此类推。想要改用Instance,可以调用Date实例的toInstance()方法来取得,如果有个Instance实例,可以使用Date的静态方法from()转为Date。

2.人类时间观点的API
(1)LocalDateTime、LocalDate、LocalTime:不具时区的时间与日期定义。
•LocalDateTime:包括日期与时间

•LocalDate:只有日期,如果设定不存在的日期,会抛出DateTimeException

•LocalTime:只有时间
(2)ZonedDateTime、OffsetdateTime:如果你的时间日期需要带有时区,可以基于LocalDateTime、LocalDate、LocalTime等来补充缺少的信息。
(3)Year、YearMonth、Month、MonthDay:如果想要取得代表月份的数字,不要使用oridinal()方法,因为oridinal()是enum在定义时的顺序,从0开始,想要取得代表月份的数要通过getValue()方法。具体例子如下:

import java.time.Month;
import static java.lang.System.out;

public class MonthDemo {
	public static void main(String[] args) {
		for(Month month : Month.values()) {
			out.printf("original: %d\tvalue: %d\t%s%n", 
					month.ordinal(), month.getValue(), month);
		}
	}
}

3.对时间的运算
(1) TemporalAmount
(2) TemporalUnit
(3) Temporal
(4) TemporalAccessor

教材学习中的问题和解决过程

暂无

代码调试中的问题和解决过程

问题:

解决过程:通过百度原因,是因为输出时的参数‘%d’和输出参数的个数不同,后来发现自己将逗号写成加号导致。看来写代码需要更加仔细。

本周代码托管截图

https://git.oschina.net/xyh20145226/java-besti-is-2015-2016-2-20145226-2/tree/master/src?dir=1&filepath=src&oid=521ad5dd7b419812d6b342bb970ba6c33cd6c7b4&sha=45fff2cdd5eba8ebe469473c18d6c37d17c87529
寒假已全部完成。

学习总结

经过这两章节的学习,让我对于java的使用和基础内容有了更深一步的认识。感觉随着学习的不断深入,了解的越来越多,自己对于专业学习有了更深的兴趣,之后的更深的内容相信也能更轻松的掌握。

posted @ 2017-02-09 01:55  夏艺华20145226  阅读(389)  评论(2编辑  收藏  举报