[Java8 新特性]

一.Lambda 表达式

lambda 表达式,是1.8引入的全新语法特性,该特性可以简化以前的匿名内部类写法,实现把一段代码当做一个参数传递给某个函数。lambda 表达式使用在 函数式接口传参的场景下,也就是说,如果一个方法的参数是一个函数式接口,那么就可以使用lambda表达式。

1.1 语法

函数式接口   对象名 =  
     (  [参数,....]  ) ->  { } ;     

箭头左侧 : 参数列表
箭头右侧 : 方法体

1.2 语法精简

image.png

1.3 体验

 Runnable 2

1.4 接口回调原理和流程

image.png

二.函数式接口

所谓函数式接口就是指一个接口中只有一个抽象方法,函数式接口可以使用@FunctionInterface 注解标注。可以检查一个接口是否为满足函数式语法。
java 提供了 4种非常常见的函数式接口

2.1 消费型

Consumer 接口,抽象方法为 accept 接收参数 无返回。 用于提供消费逻辑重写。

@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}    

2.2 供给型

Supplier 无参数,有返回一个值,类型由泛型确定。用于提供创建逻辑重写。

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

2.3 函数型

Function<T, R> 有参数有返回值,参数类型 和 返回值类型分别由 T 与 R决定。用于提供处理逻辑重写。

@FunctionalInterface
public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

2.4 断言型

Predicate 接收一个参数,返回boolean 参数类型由 T 确定。用于提供判断逻辑重写。

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}

**方法引用 **

如果lambda实现的内容已经存在一个现成的方法,这样就不用谢lambda了可以直接使用这个现成的方法。

引用方式:
对象::实例方法
类名::静态方法
类名::实例方法
类名::new 构造器引用

package methodref;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

/**
 * 方法引用: 如果一个lambda 所表达是方法有现成的方法实现了,就可以使用这个现成方法
 *           如果现有的方法参数和返回值和即将要写的lambda表达一致,可以引用这个现有方法。
 *  1. 实例方法引用  对象::实例方法
 *  2. 静态方法引用  类名::静态方法
 *  3. 类实例方法引用 类名::实例方法
 *  4. 类构造器引用   类名::new
 */
public class TestMethodRef {
    public static void main(String[] args) {

        //实例化list
        List<String> list = Arrays.asList("刘德华","景甜");

        //1. 对象::实例方法引用
        list.forEach( System.out::println );

        //2. 类::静态方法引用
        list.forEach( WX::show  );


        System.out.println("==============================================");
        List<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog("A"));
        dogs.add(new Dog("B"));
        dogs.add(new Dog("C"));
        dogs.add(new Dog("D"));
        
        //3. 类::实例方法引用
        dogs.forEach( Dog::show );

        //4. 类::new   构造方法引用
        Dog dog = createDog(Dog::new);
        System.out.println(dog);

    }

    //供给型接口使用
    public static Dog createDog(Supplier<Dog> obj){
        System.out.println("aaa");
        Dog dog = obj.get();
        System.out.println("sss");
        return dog;
    }
}

//测试类静态方法引用
class WX{
    public  static void show(String str){
        System.out.println(str);
    }
}

class Dog{
    String name;

    public Dog() {
    }

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }

    //测试类实例方法引用
    public  void show(){
        System.out.println(this.getName());
    }
}

三.Stream 流

3.1 流的概念

流Stream 这里的流是数据操作流,是流程的流,而非传递数据的流。Stream 抽象的是对数据的操作,自己并不存储数据,而是缓存对数据的一系列中间操作,这些操作会延迟执行,直到执行终止操作。事实上每次中间操作都会返回一个新的流。一个流一旦执行终止操作,将不可再使用了。
image.png

3.2 创建流方式

3.2.1 Collection集合
//1. 通过集合创建流 ( 最高频使用 )
Stream<Employee> stream1 = list.stream();

3.2.2 Arrays创建
//2. Arrays工具类创建
String[] arr = {"香蕉","苹果","菠萝"};
Stream<String> stream2 = Arrays.stream(arr);

3.2.3 Stream创建
//3. Stream 静态方法创建 of
Stream<Integer> stream3 = Stream.of(1, 2, 3, 4, 5, 6, 8);

3.3 中间操作

准备数据

//准备数据
List<Employee> list = new ArrayList<>();
list.add( new Employee("小刘","歌手","男",1200.0 ) );
list.add( new Employee("小张","演员","男",1400.0 ) );

3.3.1 filter() 过虑
//list.stream().filter( e-> e.getJob().equals("程序员")  ).forEach( e-> System.out.println(e) );

3.3.2 limit() 限制
// 限制条数
//list.stream().limit(3).forEach(e-> System.out.println(e));

3.3.3 skip() 跳过
// 跳过
// list.stream().skip(3).forEach(e-> System.out.println(e));

3.3.4 distinct去重
//去重
// list.stream().distinct().forEach(e-> System.out.println(e));

实体类需要重写equeals()方法

3.3.5 map投影
//投影
//list.stream().map( e-> e.getJob()  ).forEach(e-> System.out.println(e));

3.3.5 sorted()排序
list.stream().sorted(  (o1, o2) -> {  return  o2.getSal()-o1.getSal()>0?1:-1;}).forEach(e-> System.out.println(e));

3.4.6 parallel() 并行流
 list.stream().filter( (e)->{ return e.getGender().equals("男") ; }  ).parallel().forEach(e-> System.out.println(e));

3.4 终止操作

3.4.1 forEach
list.stream().forEach(e-> System.out.println(e));

3.4.2 min()
Optional<Employee> min = list.stream().max((o1, o2) -> o1.getSal() > o2.getSal() ? 1 : -1);
Employee employee = min.get();

Optional 是一种容器,只保存一个值通过 get方法取出值。

3.4.3 max()
Optional<Employee> max = list.stream().max((o1, o2) -> o1.getSal() > o2.getSal() ? 1 : -1);
Employee employee = max.get();

Optional 是一种容器,只保存一个值通过 get方法取出值。

3.4.4 count()
long num = list.stream().filter(e -> e.getGender().equals("男")).count();

3.4.5 collect()
  • 收集
List<Employee> collect = list.stream().filter((e) -> e.getJob().equals("演员") && e.getSal() >= 3000).
    collect(Collectors.toList());
System.out.println(collect);

Collectors.toList() 收集到一个List集合中
Collectors.toList() 收集到一个Set集合中

  • 分组
Map<String, List<Employee>> groups = list.stream().collect(Collectors.groupingBy((e) -> { return e.getJob();}));

for ( String key   : groups.keySet()){
    System.out.println("-------------"+key+"------------------");
    System.out.println( groups.get(key)  );
}

Collectors.groupingBy( lambda 给出分组依据 ) 本例中根据 job 分组

四.新的日期API

4.1 引入新日期原因

旧版的日期API主要存在的问题就是 线程不安全,还有就是混乱,体系不完整不全面。
SimpleDateFromat C1alendar 工具存在线程安全性问题。

4.2 新的日期类

LocalDate 日期
// 本地日期(系统时间) now()
LocalDate date = LocalDate.now();
System.out.println(date);

// 本地日期(指定时间) of(year,moonth,day )
LocalDate localDate = LocalDate.of(2021, 5, 13);
System.out.println(localDate);

LocalTime 时间
//本地时间 (系统) now()
LocalTime time = LocalTime.now();
System.out.println(time);

//本地时间(指定) of(hour,minute,second)
LocalTime time2 = LocalTime.of(12,30,50);
System.out.println(time2);

LocalDateTime 日期时间
// 本地日期时间(系统时间)
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
// 本地日期时间(指定的)
LocalDateTime localDateTime1 = LocalDateTime.of(2008, 8, 8, 8, 8, 8);
System.out.println(localDateTime1);

Instant 时间戳

标准时刻,不包含时区信息。

Instant now = Instant.now();
System.out.println(now);

ZoneId 时区
// 查询所有时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
//zoneIds.forEach(System.out::println);

// 查询本地时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);

4.3 日期格式化

新日期格式化使用 DateTimeFormatter 格式化工具类。通过静态方法 ofPattern 创建实例并指定格式化模板。

//日期格式化
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String mydateStr = date.format(df);
System.out.println(mydateStr);

4.4 新旧日期转换

Date 转 LocalDateTime
System.out.println("--------------------- Date 转 LocalDateTime --------------------------------");
Date oldDate = new Date();
//转成 时间戳
Instant inst = oldDate.toInstant();
// 时间戳 + 时区
LocalDateTime newDate = LocalDateTime.ofInstant(inst, ZoneId.systemDefault() );

System.out.println(newDate);

LocalDateTime 转 Date
System.out.println("-----------------------LocalDateTime 转 Date------------------------------");
Instant inst2 = dateTime.atZone(ZoneId.systemDefault()).toInstant();
Date oldDate2 = Date.from(inst2);
System.out.println(oldDate2);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值