Java8的新增特性
Java8增加了什么?
1.Lambda表达式
2.JavaScript的引擎
3.新的日期与时间Api
4.简洁的配置文件
5.jvm删除了永久代(premanent generation)
6.增强的注解功能
本文着重叙述
1.Lambda表达式
2.Stream
3.时间api
一、Lambda表达式
- 为什么使用Lambda表达式:
a. Java是面向对象的语言不能像函数式语言嵌套定义方法
b. 匿名内部类智能存在于创建他的线程中,不能运行在多线程中,无法发挥多核硬件
c. 匿名内部类语法复杂- 调用内部类的上下文中,指引和this的指代容易混淆、
- 类加载和创建实例的语法不可避免
- 不能引用外部的非final对象
- 不能抽象化控制流程
- Lambda语法包括:
a. 参数列表
b.箭头符号"->"
c.代码块
eg: lambda简化Runnable接口
原来:
public class Main {
public static void main(String[] args) {
new Runnable(){
@Override
public void run(){
System.out.println("匿名内部类实现RUnnable接口");
}
}.run();
}
}
现在:
public class Main {
public static void main(String[] args) {
int i=1;
Runnable r=()->{
System.out.println("Lambda表达式实现Runnable接口");
System.out.println("i="+i);
//i++;错误:不允许在lambda表达式中直接修改外部变量的值
};
r.run();
}
}
eg:Lambda实现自定义接口并模拟登陆
原来:
class Test{
public static void main(String[] args) {
new Action(){
@Override
public void execute(String content){
System.out.println(content);
}
}.execute("jdk1.8的匿名内部类实现");
}
static interface Action{
void execute(String content);
}
}
现在:
class Test{
public static void main(String[] args) {
Action login=(String content)->{
System.out.println(content);
};
login.execute("jdk1.8的Lambda语法操作");
}
static interface Action{
void execute(String content);
}
}
二、Stream接口
- Stream的定义:
a. Stream在java8中被定义为泛型接口;
b. Stream接口代表数据流,与IO流不同;
c. Stream不是数据结构,不直接存储数据;
d. Stream通过管道操作数据;
e. 创建Stream接口实现类的对象;stream():创建一个Stream接口实现类的对象。
如:Stream<Person> stream=people.stream(); - 关于管道:
a. 代表一个序列
b. 管道包含以下组件:- 数据集:集合、数组等;
- 零或多个中间业务。如过滤器;
- 一个终端操作,如foreach
三、过滤器
- 定义:用给定的条件在源数据基础上过滤出新的数据,并且返回一个Stream对象。
- 过滤器包含匹配的谓词。
如:判断p对象是否为男性的lambda表达式:
Stream<Person> stream=people.stream();
stream=stream.filter(p->p.getGender()=='男');
案例:
- People类:
public class People {
public static enum Sex{
MALE,FEMALE;
}
private String name;
private Sex gender;
private int age;
private double height;
public String getName() {
return name;
}
public Sex getGender() {
return gender;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public void setName(String name) {
this.name = name;
}
public void setGender(Sex gender) {
this.gender = gender;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(double height) {
this.height = height;
}
public People(String name, Sex gender, int age, double height) {
this.name = name;
this.gender = gender;
this.age = age;
this.height = height;
}
public People() {
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", gender=" + gender +
", age=" + age +
", height=" + height +
'}';
}
}
- TestPeople类:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class TestPeople {
public static void main(String[] args) {
List<People> people=creatPeople();
Stream<People>sp=people.stream().filter(p0 -> p0.getGender()!=People.Sex.MALE);
sp.forEach(
p0->System.out.println(p0.toString())
);
}
static List<People> creatPeople(){
List<People> people=new ArrayList<People>();
People p0=new People("1", People.Sex.FEMALE,1,1.23);
people.add(p0);
p0=new People("12", People.Sex.MALE,2,2.23);
people.add(p0);
p0=new People("123", People.Sex.FEMALE,3,3.23);
people.add(p0);
return people;
}
}
结果:
//过滤掉了男性
People{name='1', gender=FEMALE, age=1, height=1.23}
People{name='123', gender=FEMALE, age=3, height=3.23}
四、DoubleStream接口
- 定义:DoubleStream接口表示元素类型是double的数据源
- 常用方法:
a. stream.max().getAsDouble():获取流中数据集的最大值。
b. stream.min().getAsDouble():获取流中数据集的最小值。
c. stream.average():平均值。
案例:使用DoubleStream接口,筛选出其中名字中带有数字“1”的人的平均身高
- mapTODouble是将筛选的数据放到一个数据源中;
- average()返回值是OptionalDouble类型的,所以需要.getAsDouble();
public static void main(String[] args) {
List<People> people=creatPeople();
Stream<People>sp=people.stream().filter(p0 -> p0.getGender()!=People.Sex.MALE);
double ave=sp.filter(p->p.getName().indexOf("1")>=0)
.mapToDouble(p->p.getHeight())
.average().getAsDouble();
System.out.println(ave);
}
//2.23
五、LocalDate类
LocalDate使用ISO日历表示年月日
常用方法:
- LocalDate.now();获取系统当前日期
System.out.println(LocalDate.now());
//2018-06-26
- LocalDate.of(int year,int month,int dayOfMonth)按照指定日期创建LocalDate对象
- LocalDate.now().
- getYear():返回日期中的年份
- getMonth():返回日期中的年份
- getDayOfMonth():返回月份中的第几天
以上三种方法返回int型
eg:
System.out.println(LocalDate.now().getDayOfMonth());
//26
六、LocalTime类
获取时间
常用方法:
- LocalTime.now():获取当期时间//14:32:58.536
- LocalTime.of(int hour,int minute,int second)按照指定日期创建LocalDate对象
- LocalTime.now().
- getHour():返回小时
- getMinute():返回分钟
- getSecond():返回秒
用法同上
七、LocalDateTime类的常用方法
LocalDateTime类用于获取时间和日期
常用方法:
- localDateTime.now();获取系统当前时间
- LocalDateTime.of(int year,int month,int dayOfMonth,int hour,int minute,int second)按照指定日期和时间创建LocalDateTime对象
- getYear():返回日期中的年份
- getMonth():返回日期中的年份
- getDayOfMonth():返回月份中的第几天
- getHour():返回小时
- getMinute():返回分钟
八、DateTimeFormatter类
用于将字符串解析为日期
常用方法:
- static ofPattern(String pattern);作用:按pattern字符串指定的格式创建DateTimeFormatter对象
- LocalDateTime.parse(strDate,formatter);按照formatter对象的格式规范strDate后返回一个标准LocalDateTime
eg:
//规定格式
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd:HH:mm:ss");
//转换格式并打印
System.out.println(LocalDateTime.parse("2014-04-01:13:24:01",formatter).toString());
九、ZonedDateTime类
用于处理日期和时间与相应的时区。
常用方法:
- ZonedDateTime.now()获取系统当前日期和事件。
- String format(DateTimeFormatter formatter)按照指定模板将日期对象格式化为一个字符串。
eg:
ZonedDateTime zdt=ZonedDateTime.now();
DateTimeFormatter ft=DateTimeFormatter.ofPattern("MM/dd/yyyy:HH:mm:ss");
String strDa=zdt.format(ft);
System.out.println(strDa);
// 06/26/2018:15:37:10