JDK1.8新特性

JDK1.8新特性

核心就是Lambda表达式和Stream Api

简介:1.速度更快

2.代码更少(新的表达式Lambda)

3.强大的StreamApi

4.便于并行

5.最大化减少空指针异常 (Optional)

1.Lambda 表达式

​ Lambda表达式是一个匿名函数 ,我们可以吧Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、灵活的代码。作为一种更紧凑的代码风格,让Java的语言表达能力得到了提升。

jdk1.8中 引入了新的操作符 -> 可以称作为箭头操作符 或者Lambda操作符

操作符 -> 把 Lambda表达式分成两部分 (参数列表)-> Lambda体

//排序的1.7写法  匿名内部类
Comparator<Integer> com =new Comparator<Integer>() {
             @Override
            public int compare(Integer o1, Integer o2) {
                 return Integer.compare(o1, o2);
            }
         };

/**
 * 1.8 Lambda表达式
 */
Comparator<Integer> comparator=(x,y) -> Integer.compare(x, y);


public void function(Interface ...)
  //调用function方法  使用 静态内部类 
  function(new Interface(){
	@Override
    .....
  });
  //调用function方法  使用 Lambda表达式
function( 重写的方法参数() -> 方法体    )
  

在这里插入图片描述

注意: 如果在Lambda中使用同级的属性 这个属性必须为final 虽然可以不写final,但是不能改变该变量的值,否则就会编译出错.

在这里插入图片描述

注意: 如果只有一个参数 小括号可以省略不写

在这里插入图片描述

注意: 如果Lambda体有多条语句 必须要加一对大括号

注意: Lambda方法形参的数据类型可以加 也 可以不加

2.函数式接口

注意:只有一个方法的接口叫做函数式接口,Lambda表达式需要函数式接口的支持 jdk中提供了 @FunctionalInterface 注解来检查是否是函数式接口

内置四大核心函数式接口

Consumer< T >: 消费型接口(只传参不返回) — 无返回值 方法体 void accept(T t);

Supplier< T > : 供给型接口(只返回) — 方法体 T get();

Function< T , R >:函数型接口(两个参数,传1返2):---- 方法体 R apply( T t);

Predicate< T >: 断言型接口 ----方法体 boolean test( T t);

其他内置函数式接口

函数式接口参数类型返回类型用途
BiFunction<T,U,R>T,UR操作T,U返回R 包含的方法为
R apply(T t,U u);
UnaryOperatorTT传T返T
BinaryOperatorT,TT传两个T 返T
BiConsumer<T,U>T,Uvoid传T,U 无返回
ToIntFunction
ToLongFunction
ToDoubleFunction
Tint
long
double
传T 返 Int / long / double
IntFunction
LongFunction
DoubleFunction
Int
long
double
R传 Int / long / double ,返R

3.方法引用与构造器引用

方法引用

方法引用: 若Lambda 体中的内容有方法已经实现了,我们可以使用“ 方法引”

(可以理解为Lambda的另一种表现形式)

注意:一定要是重写的方法要和方法体中调用的方法的参数和返回值相同(除非语法三)

主要有三种语法:

1) 语法一

​ 对象名 :: 实例方法名

在这里插入图片描述

String t="方法引用";
        Test test =System.out::print;
		//Test test =System.out::print 相当于 Test test=s -> System.out.println(t) 前提是 重写的方法的参数和返回值要和调用的方法返回值相同 否则编译器会报错
//      Test test=s -> System.out.println(t);
        test.Test1(t);
2) 语法二

​ 类名 :: 静态方法名

在这里插入图片描述

3) 语法三

​ 类名 :: 实例方法名

在这里插入图片描述

构造器引用

格式 : ClassName :: new

注意: 使用构造器引用时,接口的方法参数和构造器的参数一定要对应
在这里插入图片描述

数组引用

语法: Type[ ] :: new

注意: 只能和Function接口配合使用

在这里插入图片描述

4.Stream API

Stream简介

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

Stream的操作

​ 多个Stream中间流可以连接起来形成一条流水线,除非流水线上触发终止操作,否则中间操作不会被执行 任何的处理!而在终止操作时一次性全部处理,被成文惰性求值或者延迟加载 ;

一.创建Stream流

​ 1.可以通过Collection 系列集合的 stream() 串行流 或 parallelStream() 并行流;

List<String> list=new ArrayList<String>();
Stream<String> stream = list.stream();

​ 2.通过Arrays.stream() 方法获取数组流

Stream<Integer> stream2 = Arrays.stream(new Integer[] {1,2,3});

​ 3.通过Stream的静态方法of()

Stream<String> of = Stream.of("a","b","c");

​ 4.1.创建无限流-迭代

Stream<Integer> iterate = Stream.iterate(0,(x) -> x+2 );
iteaate.forEach(System.out::println);
//会产生无限个数 从0 开始 累计加2
//第二个参数类型为UnaryOperator<T>  传T返T

​ 4.2.创建无限流-生成

Stream.generate(() -> Math.random());//无限生成随机小数
//参数类型为Supplier<T>  生产者
二. Stream的中间操作
1.筛选与切片

​ filter–>接受Lambda表达式,从流中排除某些元素

filter的方法定义 Predicate //断言型接口 传T 返回boolean
Stream<T> filter(Predicate<? super T> predicate);

​ limit–>截断流,使元素不超过给定量

Stream<T> limit(long maxSize);

​ skip–>跳过元素,返回一个扔掉了前n个元素的流,若流中元素小于n,则返回个空流

Stream<T> skip(long n);

​ distinct–>筛选 去重,通过流所生成的hashCode()和equals() 进行去重

Stream<T> distinct();
2.映射

​ map–>接受Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
//传T 返R

​ flatMap–>接受一个函数作为参数,将流中的每个流 拆分组合成一个流

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
3.排序

排序: 自然排序:Comparable 定制排序 Comparator

List list=Arrays.asList(“aaa”,“bbb”,“ccc”);

    //自然排序  使用的是Comparable
    list.stream()
        .sorted()
        .forEach(System.out::println);
    
    List<Pojo> list2=Arrays.asList(new Pojo("aaa",10),new Pojo("bbb",20));
  //定制排序  使用的是Comparator
    list2.stream()
        .sorted((x1,x2) -> {
            if (x1.getAge()==x2.getAge()) {
                return x1.getName().compareTo(x2.getName());
            }else {
                return x1.getAge().compareTo(x2.getAge());
            }
        })
        .forEach(System.out::println);
三.Stream的终止操作

1.查找和匹配

return boolean

​ allMatch–>检查是否匹配所有元素

​ anyMatch–>检查是否至少匹配一个元素

​ noneMatch–>检查是否没有匹配所有元素

return Optional

​ findFirst–>返回第一个元素

​ findAny–>返回当前流中的任意元素

return long

​ count–>返回流中的元素个数

return Optional

​ max–>返回流中的最大值

​ min–>返回流中的最小值

2.规约

​ reduce(T indentity,BinaryOperator)–>可以将流中的元素反复结合起来,得到一个值 类似于叠加 或者是 计数器

List<Integer> list=Arrays.asList(1,2,1,3);
        Integer reduce = list.stream()
            //jdk1.8提供的求和方法
            .reduce(0, Integer::sum);
        
        List<Pojo> list2=Arrays.asList(new Pojo("aaa",10),new Pojo("bbb",20));
        Optional<Integer> reduce2 = list2.stream()
             .map(Pojo::getAge)
             .reduce(Integer::sum);

3.收集

​ collect–>将流转换为其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总得方法

 List<Integer> collect = list2.stream()
             .map(Pojo::getAge)
             .collect(Collectors.toList());
//就是把重新转换成其他的元素 可以是集合 参数使用工具包Collectors里的静态方法 Collectors中的toCollection(List::new);方法比较强大 可以转换成任意集合,只需传入相应类的对象就行
四.并行流和串行流
 **并行流**就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。 //底层使用Fork/Join框架实现

串行流就是流的处理任务是串行化的。

Java8中对并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性的通过parallel() 与sequential() 在并行流和顺序流中间进行切换。

​ parallel() 转换成并行流 sequential() 顺序流

5.接口中的默认方法与静态方法

​ Java1.8中提供了默认接口实现 就是在接口中除了全局静态常量和抽象方法外还有默认方法的实现 如果是静态方法也可以有方法体 声明如下

public interface MyInterface{
  default void function(){
    Syso("111");
  }
  static void functionStatic() {
         System.out.println("111");
     }
}

这样就会导致接口或父类之间的方法实现重复

​ 若一个实现类的接口和父类中有重名的方法实现的话 默认类方法优先

​ 若两个接口有相同的方法名称和参数列表的话,就强制需要实现类重写或者继承某个接口的方法: 接口名.super.方法

 public interface Test {
     default void function() {
         System.out.println("111");
     }
}

 public interface Test2 {
     default void function() {
         System.out.println("111");
     }
}

public class ClassImpl implements Test,Test2{
  public void function(){
    Test.super.function();
  }
}

6.新时间日期API

​ java8提供了新的日期API,来取代之前的Date类。因为之前的日期API是1.0版本出的,大多数方法都已经过期,而且最重要的是Date日期类不是线程安全的

​ 新的日期API在java.time包下比如: LocalDate、LocalTime、LocalDateTime、Instant…

​ Duration用于时间的加减 between()

​ Zonedxxx为时区类

7.其他新特性

​ java8提供了重复注解和类型注解

//在jdk1.7中只能有一个注解 但是在1.8可以修饰多个
@MyAnnotation("aaa")
@MyAnnotation("aaa")
public void show(){
  
}
//但是该注解必须要使用@Repeatable(xxx.class) 注解 xxx也是 注解 定义如下:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
 public @interface MyAnnotactions {
   //必须是修饰注解的数组
     MyAnnotation[] value();
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值