JAVA8新特性 函数式接口 lambda表达式 StreamAPI 日期时间API

8 篇文章 2 订阅

1.Java8新特性

1)默认方法:
    默认方法就是一个在接口里面有了一个实现的方法    
2)方法引用:
    方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。
    与lambda联合使用,可以使语言的构造更紧凑简洁,减少冗余代码。
3)Lambda表达式:
    Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
4)Stream API:
    新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
5)Date Time API:
    加强对日期与时间的处理
6)Optional类:
    Optional类已经成为Java 8 类库的一部分,用来解决空指针异常。

1.1 关于接口

1.1.1 原始接口

接口定义

接口的作用:定义一套标准、规范,一个公共的规则,所以接口中的之声明方法签名,不提供方法体,具体实现由实现类完成。

接口中的属性:public static final,即只能是常量

接口中的方法:public abstract,即方法必须为抽象方法

接口没有构造方法,所以不能实例化

接口可以通过extends继承其他接口

接口的实现必须实现接口所有方法,否则该类应该抽象类

 

接口的作用

1)多继承,java对象只能有一个父类,通过接口可以实现多继承

2)有利于代码规范,定义接口,可以让不同的开发人员按照统一规范来完成项目的开发工作,防止开发人员随意命名,导致命名不清晰,代码混乱等

3)降低项目的耦合度,提高可扩展性。一个类被多个地方调用,当其中一个地方发生业务改变时,通过定义一个新的实现类来解决即可,而避免改变所有调用的地方。

1.1.2 接口新特性(1.8)

接口的默认方法

接口中特殊的方法,被default修饰,可以包含方法体

  public interface IHello {
    void sayHi();
    default void sayBye() { }
  }

作用:扩展接口功能,不破坏现有代码,让接口扩展新的功能。默认方法跟接口中其他方法不同,它是可选的。子类可以根据需求选择是否需要重写该方法。

注意:若一个类实现了多个接口,那么多个接口中不应该包含相同的默认方法,编辑会报错,除非重写该默认方法。

接口中的静态方法

等同于类中的静态方法,调用时可不需要实现接口或实例化接口的实例,来完成方法的调用。

  public interface IHello {
    static void sayHello() {}
  }

1.2 Lambda表达式

1.2.1 函数式接口

a.函数式接口

有且仅包含一个抽象方法的接口(可以包含一个或多个静态或默认方法)。

1.8之前: 
   java.lang.Runnable java.util.concurrent.Callable java.util.Comparator java.io.FileFilter 
1.8之后: 
   java.util.function、Predicate<T> 、Supplier<T>

b.使用场景

Lambda表达式,使用Lambda表达式可以简化匿名内部类的实现

@FunctionalInterface注解:
    该注解来定义接口,编译器强制检查接口中是否有且仅有一个抽象方法,如果不是,则编译出错

1.2.2 Lambda表达式

Lambda 允许把函数作为一个方法的参数或返回值(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法: 
   (parameters) -> expression 或 (parameters) ->{ statements; } 
简化版:
   ()-> {} ()代表参数,{}代表方法体,->代表运算符 
注意: 
   1) 所有参数类型,均可以省略
   2) 当参数只有一个,小括号可以省略 
   3) 无返回值情况,当方法体只有一条语句,可以省略大括号 
   4) 有返回值情况,当方法体只有一条语句,可以省略大括号和return

示例:

1)无参无返回

public interface IHello {
    void sayHello();
}
IHello iHello = () -> {System.out.println("");};

2)单参,无返回 

public interface IHello2 {
     void sayBye(String a);
}
IHello2 iHello2 = (a) ->{System.out.println("a:" + a);};

 3)多参,无返回

public interface IHello3 {
    void sayHi(int a,int b);
}
IHello3 iHello3 = (a,b)->{ System.out.println(a + b);};

4)无参数,有返回 

public interface IHello4 {
    int sayHi();
}
IHello4 iHello4 = () -> {return 1;};

5)单参数,有返回 

public interface IHello5 {
    int sayHi(int a);
}
IHello5 iHello5 = (a) ->{return a*10;};

6)多参数,有返回值 

public interface IHello6 {
    int sayHi(int a,int b);
}
IHello6 iHello6 = (a,b) -> {return a+ b;};

1.2.3 Lambda表达式的特殊使用

a.方法引用

Lambda表达式可以直接指向一个已经实现的方法

要求:①:该方法的参数数量和参数类型必须跟接口中的方法一致 ②:该方法的返回值类型必须与接口中的一致

public interface IHello5 {
    int sayHi(int a);
}
public static int change(int a) {
    return a;
}
IHello5 iHello5 = a -> change(a);

b.双冒号(::)的使用

普通方法:(参数是某个对象,调用该对象的方法)
public interface IPerson {
    int getPerson(Person person);
}
原装版:IPerson iPerson = (person) -> {return person.getAge();};
简化版:IPerson iPerson = Person::getAge;
​注意:参数对象调用的方法必需是无参
构造方法:(返回值是某个对象)
public interface IPerson {
    Person getPerson();
}
原装版:IPerson iPerson = () -> {return new Person();};
简化版:IPerson iPerson = Person::new;
​
注意:调用的为无参构造

1.2.4 系统内置函数式接口

Consume:参数为T,无返回
public interface Consumer<T> {
    void accept(T t);
}
​
Supplier:无参有返回
public interface Supplier<T> {
    T get();
}
​
Predicate:泛型参数T,返回值boolean
public interface Predicate<T> {
    boolean test(T t);
}
​
Function:参数为T,返回值为R
public interface Function<T, R> {
    R apply(T t);
}

1.3 StreamAPI

1.3.1 什么是Stream

Stream:中文成为"流",一种对集合或者数组进行处理的工具,又被称为"操作符";操作符分类两类:中间操作符、终止操作符。一般来讲,流不会修改原来的数据,它会将操作后的数据保存到另一个对象中。

Stream使用步骤:

1)创建Stream对象

2)使用中间操作符进行操作

3)使用终止操作符

1.3.2 创建stream对象

stream对象的获取,可以分为数组、list、set、map(可以得到key的set集合、value的list集合)

数组

String[] strArray = new String[] {"apple", "banana", "orange", "waltermaleon", "grape"};
​
Stream.of(strArray)//第一种
Arrays.stream(strArray)//第二种

list、set

List<Student> stuList = new ArrayList<Student>();
stuList.stream();//串行
stuList.parallelStream();//并行
​
Set<Student> set = new HashSet<>();
set.stream();
set.parallelStream();

1.3.2 中间操作符

对数据执行操作后,数据依然可以传递给下一级操作符。(一般都需要传递给终止操作符,因为中间操作符返回值为Stream对象,不传递给终止操作符返回处理后的数据没有意义)

中间操作符主要分为8种:

转换操作符:
    把原始数据转换为你所需要的数据,默认可转换成int、long、double类型 map,mapToInt,mapToLong,mapToDouble 
拍平操作符:
    即拆开,把数组拆分成单个字段,默认提供了拍平成int,long,double的操作符.
    flatmap,flatmapToInt,flatmapToLong,flatmapToDouble                                              
限流操作符:
    比如数据流中有10条数据,只取其中三条 limit 
去重操作符:
    去掉重复数据 distinct 
过滤操作符:
    筛掉不想要的数据 filter 
跳过操作符:
    跳过某些元素 skip 
挑出操作符:
    对数据进行某些操作,如读取、编辑修改等 peek 
排序操作符: 
    sorted 

map转换操作符

String[] strArray = new String[] {"apple", "banana", "orange", "waltermaleon", "grape"};
Stream.of(strArray)
    .map(e -> e.length())
    .forEach(e -> System.out.println(e));

flatMap拍平操作符

 Stream.of("a-b-c-d","e-f-i-g-h")
     .flatMap(e->Stream.of(e.split("-")))
     .forEach(e->System.out.println(e));

limit限流操作符

Stream.of(1,2,3,4,5,6)
    .limit(3) //限制三个
    .forEach(e->System.out.println(e));

distinct去重操作符

Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
    .distinct() //去重
    .forEach(e->System.out.println(e));

filter过滤操作符

 Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
     .filter(e->e>=5) //过滤小于5的
     .forEach(e->System.out.println(e));

skip跳过操作符

Stream.of(1,2,3,4,5,6,7,8,9)
    .skip(4) //跳过前四个
    .forEach(e->System.out.println(e)); 

peek挑出操作符

User w = new User("w",10);
User x = new User("x",11);
User y = new User("y",12);
Stream.of(w,x,y)
    .peek(e->{e.setName(e.getAge()+e.getName());}) //重新设置名字 变成 年龄+名字
    .forEach(e->System.out.println(e.toString()));

sorted排序操作符

Stream.of(2,1,3,6,4,9,6,8,0) 
    .sorted()  //默认排序
    .forEach(e->System.out.println(e));
​
User x = new User("x",11);
User y = new User("y",12);
User w = new User("w",10);
Stream.of(w,x,y)
    .sorted((e1,e2)->e1.age>e2.age?1:e1.age==e2.age?0:-1)
    .forEach(e->System.out.println(e.toString()));
    
注意:多重三元运算符(三目运算符)嵌套
String str =  a.equals("123") ? "123" : ( b.equals("456") ? "456" : "789");
//如果a等于123,就给str赋值123;否则,如果b等于456,就给str赋值123,前面两个如果都不成立就赋值789

 

1.3.3 终止操作符

中间操作符处理数据后,须有终止操作符进行收集、消费操作。终止操作符只能用一次。

收集操作符:将数据收集起来
    collect
统计操作符:
    count
查找操作符:
    findFirst,findAny
匹配操作符:流中是否存在符合条件的元素,返回boolean值
    noneMatch、allMatch、anyMatch
最值操作符:
    max,min
遍历操作符:
    forEach
数组操作符:将数据流元素变为数组
    toArray
规约操作符:将整个数据流规约为一个值,count/min/max都属于规约
    reduce

collect收集操作符

Set<String> stringSet = 
    Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
    .collect(Collectors.toSet()) //set 容器

count统计操作符

long count = 
    Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
    .count();

查找操作符

findFirst:取流中的第一个元素
    Optional<String> stringOptional = 
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
        .findFirst();
    stringOptional.get();//得到第一个元素
​
​
findAny:获取流中任意一个元素
    Optional<String> findFirst = 
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
        .findAny();
     stringOptional.get();//得到任意一个元素,实际还是第一个

匹配操作符

boolean result = Stream.of("aa","bb","cc","aa")
                .noneMatch(e->e.equals("aa"));
noneMatch:没有一个匹配返回true
allMatch:全部匹配返回true
anyMatch:任意一个匹配返回true

最值操作符:

Optional<Integer> integerOptional = 
    Stream.of(0,9,8,4,5,6,-1)
    .max((e1,e2)->e1.compareTo(e2));//max元素中最大的
    .min((e1,e2)->e1.compareTo(e2));//min元素中最大的

reduce规约操作符

所有的元素归约成一个,比如对所有元素求和,乘等
int sum = Stream.of(0,9,8,4,5,6,-1)
    .reduce(0,(e1,e2)->e1+e2);

toArray 数组操作符

转成数组
Object[] objects=Stream.of(0,2,6,5,4,9,8,-1)
                .toArray();

 

1.4 日期时间API

1.4.1 新旧版本的区别

旧版本:
    1)线程不安全
    2)设计较差,java.util、java.sql都有日期类,而格式化类却在java.text包下,设计不合理
    3)时区处理麻烦:日期类不提供国际化,没有时区支持
新版本:(java.time包)
    1)Local(本地):简化了日期时间的处理,没有时区问题
    2)Zoned(时区):通过制定时区处理日期时间问题  

1.4.2 本地化日期时间API

主要涉及的类为:LocalDate、LocalTime、LocalDateTime

方法描述
now()静态方法,根据当前时间创建对象
of()静态方法,根据指定日期/时间创建 对象
plusDays, plusWeeks, plusMonths, plusYears向当前 LocalDate 对象添加几天、 几周、几个月、几年
minusDays, minusWeeks, minusMonths, minusYears从当前 LocalDate 对象减去几天、 几周、几个月、几年
plus, minus添加或减少一个 Duration或 Period
withDayOfMonth, withDayOfYear, withMonth, withYear将月份天数、年份天数、月份、年 份修改为指定的值并返回新的 LocalDate对象
getDayOfMonth获得月份天数(1-31)
getDayOfYear获得年份天数(1-366)
getDayOfWeek获得星期几(返回一个 DayOfWeek 枚举值)
getMonth获得月份, 返回一个 Month枚举值
getMonthValue获得月份(1-12)
getYear获得年份
until获得两个日期之间的 Period 对象, 或者指定 ChronoUnits的数字
isBefore, isAfter比较两个 LocalDate
isLeapYear判断是否是闰年

 

******对象创建******
LocalDate localDate = LocalDate.now();//获取当前日期
LocalDate localDate = LocalDate.of(year, month, dayOfMonth);//获取特定日期
​
******获取年、月、日信息******
int year = localDate.getYear();//年
int monthValue = localDate.getMonthValue();//月
int dayOfMonth = localDate.getDayOfMonth();//日
int dayOfYear  = localDate.getDayOfYear();//一年中的第几天
int dayOfWeek = localDate.getDayOfWeek();//周几
​
******枚举对象ChronoField获取年、月、日信息******
int year = localDate.get(ChronoField.YEAR);
int month = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.get(ChronoField.DAY_OF_MONTH);
​
******日期修改******
LocalDate date = localDate.withYear(year);//变为指定年
LocalDate date = localDate.withMonth(month);//变为指定月
LocalDate date = localDate.withDayOfMonth(dayOfMonth);//变为指定日
//日期添加
LocalDate date = localDate.plus(amountToAdd, unit);
LocalDate date = localDate.plusYears(yearsToAdd);
LocalDate date = localDate.plusMonths(monthsToAdd);
LocalDate date = localDate.plusWeeks(weeksToAdd);
LocalDate date = localDate.plusDays(daysToAdd)
//日期减少
LocalDate date = localDate.minnus(amountToAdd, unit);
LocalDate date = localDate.minnusYears(yearsToAdd);
LocalDate date = localDate.minnusMonths(monthsToAdd);
LocalDate date = localDate.minnusWeeks(weeksToAdd);
LocalDate date = localDate.minnusDays(daysToAdd)
​
******日期比较******
localDate.isAfter(otherDate)
localDate.isBefore(otherDate)
​
******其他方法******
int len = localDate.lengthOfMonth();//31(这个月有多少天)
boolean leap = localDate.isLeapYear();//false(是不是闰年)
localDate.toEpochDay() - specialDay.toEpochDay();//日期间隔天数

DateTimeFormatter

//解析日期
String dateStr= "2018年12月18日";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate date= LocalDate.parse(dateStr, formatter);
​
//日期转换为字符串
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy年MM月dd日 hh:mm a");
String nowStr = now .format(format);
System.out.println(nowStr);

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值