java8新特性精简版

前言——用于个人cv

个人笔记,方便自己忘了语法进行cv

一.java8新特性

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

二.常用api写法

1.Lambda:表达式

  1. 参数列表可以不写数据列表类型,因为JVM编译器通过上下文推断数据类型,即"类型推断"
(x, y) -> {
    
    Integer.compare(x,y)}
  1. 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)
  1. 变量作用域: Lambda表达式只能引用标记了final的外部局部变量,这就是说不能在Lambda内部修改定义在域外的局部变量,可以不使用final修饰,但不可以修改

2.方法引用

我们可以使用**“方法引用**”(可以理解为方法引用是Lambda表达式的另一种表现形式)
主要有有三种语法格式:

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

注意:

  • Lambda体中调用方法的参数列表与返回值,要与函数式接口中抽象方法的函数列表和返回值类型保持一致
  • 若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();//普通流
Stream<String> stream2 = list.parallelstream();//并行流

// 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,从流中留下predicate方法返回为true的元素(就是把返回为true的产品留在加工线上,其他丢掉)

limit(long maxSize)  ----> 截断流,最多保留前maxSize个元素的流(把maxSize之后的产品丢掉)

skip(long n)  ----> 跳过元素,返回一个扔掉前 n 个元素的流,若流中元素不足 n 个,则返回一个空流,与limit(n) 互补(把前n个产品丢掉)

distinct()  ----> 筛选,通过流中所生成的hashcode()equals() 去重,需要重写这两个方法()

// 示例
list.stream().filter((e) -> e.getAge > 10).limit(2L).forEach(System.out::println)

// 映射——map和flatMap用的再详细查
map(Function<? super T,? extends R> mapper) ----> 接收Lambda,将元素转换成其他形式提取信息,
						接收一个函数作为参数,该函数会被应用到每个元素上,并将映射成一个新的元素(加工产品,)


flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
				---->	接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连成一个流

//排序
sorted()  -----> 自然排序

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

3.终止操作——取出

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


// 查找与匹配
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)  ----> 可以将流中元素反复结合起来,得到一个值


并行流与顺序流

  • 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流:parallelstram()创建并行流
  • 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);


总结

仅用于个人cv

猜你喜欢

转载自blog.csdn.net/imbzz/article/details/131942910