JavaJDK8新特性

Lambda表达式

Lambda与匿名内部类对比:

public static void main(String[] args) {
        /*使用匿名内部类实现线程*/
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是匿名内部类!");
            }
        }).start();


        /*使用lambda实现线程*/
        new Thread(()->{
            System.out.println("我是Lambda");
        }).start();
    }

Lambda的标准形式:

( 参数类型 参数名称 ) -> {
代码体 ;
}
说明:
(参数类型 参数名称)表示参数列表
  {代码体}  表示方法体
  ->箭头   用来分隔参数列表和方法体

 Lambda实现原理总结:

匿名内部类,在程序编译时,会生成一个class文件

Lambda在程序运行时,会生成一个class文件。

  具体过程:

1.程序编译中,会先生成一个静态的方法,该方法为接口的实现方法

2.在执行过程中,生成一个匿名内部类,实现接口,重写抽象接口方法

3.在接口重写的方法实际上就是调用编译时生成的静态方法

Lambda的省略格式:

Lambda 标准格式的基础上,使用省略写法的规则为:
1. 小括号内参数的类型可以省略
2. 如果小括号内 有且仅有一个参数 ,则小括号可以省略
3. 如果大括号内 有且仅有一个语句 ,可以同时省略大括号、 return 关键字及语句分号
(int a) -> {
return new Person();
}

 省略后

a->new Person()

 Lambda的前提条件:

1. 方法的参数或变量的类型是接口
2. 这个接口中只能有一个抽象方法

函数式接口

函数式接口在 Java 中是指: 有且仅有一个抽象方法的接口
函数式接口,即适用于函数式编程场景的接口。而 Java 中的函数式编程体现就是 Lambda ,所以函数式接口就是可以
适用于 Lambda 使用的接口。只有确保接口中有且仅有一个抽象方法, Java 中的 Lambda 才能顺利地进行推导。
FunctionalInterface 注解
@Override 注解的作用类似, Java 8 中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注解可用于一个接口的定义上:
@FunctionalInterface
public interface Operator {
void myMethod();
}
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。不过,即
使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

Lambda和匿名内部类对比:

1. 所需的类型不一样
匿名内部类 , 需要的类型可以是类 , 抽象类 , 接口
Lambda 表达式 , 需要的类型必须是接口
2. 抽象方法的数量不一样
匿名内部类所需的接口中抽象方法的数量随意
Lambda 表达式所需的接口只能有一个抽象方法
3. 实现原理不同
匿名内部类是在编译后会形成 class
Lambda 表达式是在程序运行的时候动态生成 class

常用内置函数式接口

常用内置函数式接口介绍

1. Supplier接口

@FunctionalInterface
public interface Supplier<T> {
public abstract T get();
}
public static void main(String[] args) {
        test(()->{
            return  10;
        });
    }

    public static  int test(Supplier<Integer> supplier){
        Integer integer = supplier.get();
        System.out.println("获取到的值:"+integer);
        return integer;
    }

 2. Consumer接口

@FunctionalInterface
public interface Consumer<T> {
public abstract void accept(T t);
}
public class Test5 {
    public static void main(String[] args) {
        test(s->{
            System.out.println("我的名字是"+s);
        },"小明");

    }

    public  static  void  test(Consumer<String> consumer,String name){
        consumer.accept(name);
    }

3.Function接口  

@FunctionalInterface
public interface Function<T, R> {
public abstract R apply(T t);
}
 public static void main(String[] args) {
        test(s -> {return Integer.valueOf(s);},"100");
    }

    public static  void test(Function<String,Integer> function,String number){
        Integer n = function.apply(number);
        System.out.println("将字符串"+number+"转化成数字"+n);
    }

 4.Predicate接口

@FunctionalInterface
public interface Predicate<T> {
public abstract boolean test(T t);
}
Predicate 接口用于做判断 , 返回 boolean 类型的值
public static void main(String[] args) {
        test(s->{
            return s.contains("n");
        },"name");
    }
    public static  void test(Predicate<String> predicate,String name){
        System.out.println(predicate.test(name));
    }

Lambda表达式方法的引用

方法引用格式:

符号表示     ::

符号说明:双冒号为方法引用运算符,而它所在的表达式被称为方法引用

应用场景:如果Lambda所要实现的方案 , 已经有其他方法存在相同方案,那么则可以使用方法引用。

常见的引用方式:

1. instanceName::methodName 对象 :: 方法名
2. ClassName::staticMethodName 类名 :: 静态方法
3. ClassName::methodName 类名 :: 普通方法
4. ClassName::new 类名 ::new 调用的构造器
5. TypeName[]::new String[]::new 调用数组的构造器

1. instanceName::methodName 对象::方法名

public class Test2 {

    public String test(){
       return "我是对象::方法的引用";
    }

    public static void main(String[] args) {
        Test2 test2=new Test2();

       //方法调用
        Supplier<String> supplier2=()->{
            return test2.test();
        };
        System.out.println(supplier2.get());

         //方法引用
        Supplier<String> supplier=test2::test;
        System.out.println(supplier.get());
    }
}

 2. ClassName::staticMethodName 类名::静态方法

public class Test3 {

    public static  String test(){
        return "我是类名引用静态方法";
    }

    public static void main(String[] args) {

        //方法调用
     Supplier<String> supplier=()->{
            return Test3.test();
        };
        System.out.println(supplier.get());

        //方法引用
        Supplier<String> supplier1=Test3::test;
        System.out.println(supplier1.get());
    }

3. ClassName::methodName 类名::普通方法

public class Test4 {



    public static void main(String[] args) {

        //方法调用
        Function<String,Integer> function=(s->{
            return s.length();
        });
        System.out.println(function.apply("abc"));

        //方法引用   类名引用普通方式,实际上是将第一个参数作为方法的调用者
        Function<String,Integer> function1=String::length;
        System.out.println(function1.apply("abc"));


        BiFunction<String,Integer,String> biFunction=((s1,s2)->{
           return   s1.substring(s2);
        });
        System.out.println(biFunction.apply("abcd",2));


        BiFunction<String,Integer,String> biFunction1=String::substring;
        System.out.println(biFunction1.apply("abcd",2));

    }
}

4. ClassName::new 类名::new 调用的构造器

public class Test5 {

    public Test5() {
        System.out.println("我被构造出来了");
    }

    public static void main(String[] args) {
        //方法调用
        Supplier<Test5> supplier=()->{
            return  new Test5();
        };

        System.out.println(supplier.get());

        //方法引用
        Supplier<Test5> supplier1=Test5::new;
        System.out.println(supplier1.get());
    }
}

5. TypeName[]::new String[]::new 调用数组的构造器

public class Test6 {

    public static void main(String[] args) {

        //方法调用
        Function<Integer,String[]> function=(len)->{
            return new String[len];
        };
        String[] apply = function.apply(10);
        System.out.println(apply.length);
        //方法引用

        Function<Integer,String[]> function1=String[]::new;
        String[] apply1 = function1.apply(10);
        System.out.println(apply1.length);

    }

}

Stream流

Stream流的思想概述:

Stream 流式思想类似于工厂车间的 生产流水线 Stream 流不是一种数据结构,不保存数据,而是对数据进行加工
处理。 Stream 可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。
Stream API 能让我们快速完成许多复杂的操作,如筛选、切片、映射、查找、去除重复,统计,匹配和归约

获取Stream流的两种方式

1.根据Collection获取流

public interface Collection {
default Stream<E> stream()
}

2.根据Stream中的静态方法of获取流

public static void main(String[] args) {
// Stream中的静态方法: static Stream of(T... values)
Stream<String> stream6 = Stream.of("aa", "bb", "cc");
String[] arr = {"aa", "bb", "cc"};
Stream<String> stream7 = Stream.of(arr);
Integer[] arr2 = {11, 22, 33};
Stream<Integer> stream8 = Stream.of(arr2);
// 注意:基本数据类型的数组不行
int[] arr3 = {11, 22, 33};
Stream<int[]> stream9 = Stream.of(arr3);
}

Stream常用方法

Stream流的注意事项:

1. Stream 只能操作一次
2. Stream 方法返回的是新的流
3. Stream 不调用终结方法,中间的操作不会执行

Stream的forEach方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值