java8常用新特性


一、java8新特性

1、Lambda:表达式- - - - - Lambda允许把函数作为一个方法的参数
2、方法引用- - - - - 可以直接引用已有的java类或对象(实例)的方法或构造器
3、默认方法- - - - - 接口中一个实现的方法
4、Stream Api - - - - - 新添加的stream API(java.util.stream),把真正的函数式编程风格引入到Java中
5、Optional类 - - - - - 已经成为Java8类库的一部分,解决空指针异常
6、日期时间 API - - - - - 将日期时间的操作类集中到java.time类中

更多的新特性

二、详细简介

1.Lambda:表达式

1、参数列表可以不写数据列表类型,因为JVM编译器通过上下文推断数据类型,即"类型推断"

(x, y) -> {Integer.compare(x,y)}

2、Java8中内置的四大核心接口

Comsumer<T>  ---->  消费型接口、有去无回
			void accept(T t)
Supplier<T>  ---->  供给型接口、什么不给返回T类型
			T get()
Function<T, R>   ----->  函数型接口、给TR(TR也可以同一类型)
			R apply(T t)
Predicate<T>    ----->  断言型接口、if判断
			boolean test(T t)

3、变量作用域: Lambda表达式只能引用标记了final的外部局部变量,这就是说不能在Lambda内部修改定义在域外的局部变量,可以不使用final修饰,但不可以修改

2.方法引用

若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是Lambda表达式的另一种表现形式)
主要有有三种语法格式:

  • 对象 :: 实例方法名
  • 类 :: 静态方法名
  • 类 :: 实例方法名

注意: 1、Lambda体中调用方法的参数列表与返回值,要与函数式接口中抽象方法的函数列表和返回值类型保持一致
2、若Lambda 参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用 ClassName :: method

3.接口中的默认方法和静态方法

public interface Sized {
    // 普通抽象方法,默认是public abstract修饰的,没有方法体
    int size();

    /*
     * 默认方法,有方法体
     */
    default boolean eat() {
        System.out.println("这是默认方法");
    }
	/*
     * 静态方法,有方法体 
     */
     public static void say() {
        System.out.println("这是静态方法");
    }
}

接口默认方法的“类优先”原则
----> 若一个接口中定义了一个默认方法,而另一个父类或接口中又定义了一个同名的方法时

  • 选择父类中的方法,如果一个父类提供了具体的实现,那么接口中具有相同名称和参数列表的默认方式被忽略
  • 接口冲突,如果一个接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否默认方法),那么必须覆盖该方法来解决冲突

4.强大的Stream API

流(stream) 到底是什么呢?
---- 是数据渠道,用于操作数据源(集合、数组等) 所生成的元素序列

三步骤
1、创建Stream : 一个数据源(如集合、数组) 获取一个流
2、中间操作: 一个中间操作链,对数据源的数据进行处理
3、终止操作: 一个终止操作,执行中间操作链,并产生结果

1、创建Stream

// 1、可以通过Collection 系列接口提供的stream() 或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();

// 2、通过Arrays 中的静态方法stream() 获取数组流
Employee emp = new Employee[10];
Stream<Employee> stream = Arrays.stream(emp)

//  3、通过Stream类中的静态方法of()
Stream<String> stream = Stream.of("aa","bb","cc");

// 4、 创建无限流
// 迭代
Stream<String> stream = Stream.iterate(0,(x) -> x + 2);
stream.limit(4L).forEach(System.out::println)
// 生成
Stream.generate(() -> Math.random()).limit(5L).forEach(System.out::println)

2、中间操作

// 筛选与切片
filter(Predicate<? super T> predicate)  ----> 接收Lambda,从流中排除某些元素
limit(long maxSize)  ----> 截断流,使其元素不超过给定数量
skip(long n)  ----> 跳过元素,返回一个扔掉前 n 个元素的流,若流中元素不足 n 个,则返回一个空流,与limit(n) 互补
distinct()  ----> 筛选,通过流中所生成的hashcode()equals() 去重,需要重写这两个方法
// 示例
list.stream().filter((e) -> e.getAge > 10).limit(2L).forEach(System.out::println)

// 映射
map(Function<? super T,? extends R> mapper) ----> 接收Lambda,将元素转换成其他形式提取信息,
						接收一个函数作为参数,该函数会被应用到每个元素上,并将映射成一个新的元素
flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
				---->	接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连成一个流

//排序
sorted()  -----> 自然排序
sorted(Comparator<? super T> comparator)  ----> 定制排序

3、终止操作

// 查找与匹配
boolean allMatch(Predicate<? super T> predicate)  ----> 检查是匹配所有元素
boolean anyMatch(Predicate<? super T> predicate)  ----> 检查是否至少匹配一个元素
boolean noneMathch(Predicate<? super T> predicate)  ----> 检查是否没有匹配所有元素
Optional<T> findFirst()  ----> 返回描述此流的第一个元素的Optional如果流为空,则返回一个空的Optional
Optional<T> findAny()  ----> 返回流中的任意元素的Optional如果流为空,则返回一个空的Optional
long count() ----> 返回流中的元素的总个数
Optional<T> max(Comparator<? super T> comparator)   ----> 根据提供的 Comparator返回此流的最大元素。
Optional<T> min(Comparator<? super T> comparator)   ----> 根据提供的 Comparator返回此流的最小元素。

// 归约
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)  ----> 可以将流中元素反复结合起来,得到一个值

//收集
<R,A> R collect(Collector<? super T,A,R> collector)  ----> 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到ListSetMap),但是Collectors 实用类提供了很多静态方法,可以方便的创建常见收集器实例
// 示例
List<String> ll = list.stream().collect(Collectors.toList());

并行流与顺序流

  • 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
  • Java8 中将并行进行了优化,我们可以很容易的对数据进行并行操作,Stream API 可以声明性的通过parallel() 与 sequential() 在并行流与顺序流之间进行切换

5.Optional类

Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在 Optional 可以更好的表达这个概念,并且可以避免空指针异常

static <T> Optional<T> Optional.of(T t) ----> 创建一个Optional实例
static <T> Optional<T> Optional.empty() ----> 创建一个空的Optional实例
static <T> Optional<T> Optional.ofNullable(T t) ----> 若t 不为null,创建Optional 实例,否则空实例
boolean isPresent() ----> 判断是否包含值
T orElseGet(Supplier<? extends T> s)  ----> 如果调用对象包含值,返回该值,否则返回 s 获取的值
T osElse(T t) ----> 若果调用对象包含值,返回值,否则返回t

6.日期时间API

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

  • Local(本地) − 简化了日期时间的处理,没有时区的问题。

  • Zoned(时区) − 通过制定的时区处理日期时间。

 LocalDateTime currentTime = LocalDateTime.now();// 获取当前的日期时间
 DateTimeFormatter dt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 LocalDateTime.of(LocalDate.now(),LocalTime.MIN).format(dt); //2021-08-04 00:00:00
 
 LocalDate date1 = currentTime.toLocalDate();  // LocalDate.now() 获取年月日
 
 Month month = currentTime.getMonth(); // 月 
 int day = currentTime.getDayOfMonth(); // 天
 int seconds = currentTime.getSecond(); // 秒

Date与LocalDateTime、LocalDate、LocalTime互相转换

// Date 转成 LocalDateTime、LocalDate、LocalTime
Date date = new Date();
// 系统默认时区 服务器时区不对会导致转换后的时间不对 
ZoneId zoneId = ZoneId.systemDefault(); 
Instant instant = date.toInstant();

LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();

// LocalDateTime 转成 Date
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zoneId).toInstant();
Date date = Date.from(instant);

// LocalDate 转成 Date
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
Date date = Date.from(instant);

// LocalTime 转成 Date
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = LocalDateTime.of(localDate, localTime).atZone(zone).toInstant();
Date date = Date.from(instant);

总结

个人笔记,仅供参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值