JDK1.8之Lambda表达式,方法引用和构造引用

JDK1.8之Lambda表达式,方法引用及构造引用

Lambda表达式

Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。

举例:在对集合中的数据进行排序时,需要一个Comparator接口的匿名内部类,这里,匿名内部类就可以用Lambda表达式进行简写

public class MyTest1 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(0);
        list.add(2);
        list.add(222);
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return b-a;
            }
        });
        System.out.println(list);
        //对传入的匿名内部类,就可以使用Lambda做简化
        list.sort((a,b)->a-b);
        System.out.println(list);

    }
}
程序运行结果:
[222, 20, 2, 0]
[0, 2, 20, 222]

Lambda表达式的语法
JDK1.8 引入了一个箭头符号 ->
这个箭头符号 将Lambda表达式分为 左右两部分。 左边->右边

左边:写的是你实现的这个接口中的抽象方法的 形参列表
右边:写的是你对接口中这个抽象方法的具体实现逻辑。

public class MyTest2 {
    public static void main(String[] args) {
        //方式1:我们就采用匿名内部类的方式
        MyInterface myInterface = new MyInterface() {
            @Override
            public void show(int a, int b) {
                System.out.println(a + b);
            }
        };

        //采用Lambda表达式,对匿名内部类进行简写。
        //第一步简写。抽象方法的参数列表->具体的实现逻辑
        MyInterface myInterface1=(int a,int b)->{
            System.out.println(a + b);
        };
        
        //第二步简写:可以省略掉形参列表的参数的数据类型
        MyInterface myInterface2=( a, b)->{
            System.out.println(a + b);
        };
        
        //第三步简写:我们对抽象方法的实现逻辑,只有一行代码那么方法体的大括号可以省略不写
        MyInterface myInterface3=( a, b)-> System.out.println(a + b);
    }
}

这里注意:如果形参只有一个参数的数据类型和()括号都可以省略不写

public interface MyInterface3 {
    public abstract int show(int a);
}

public class MyTest2 {
    public static void main(String[] args) {
        MyInterface3 myInterface3 = new MyInterface3() {
            @Override
            public int show(int a) {
                return a + 100;
            }
        };
        MyInterface3 myInterface4=(int a) ->{
            return a + 100;
        };
        
        MyInterface3 myInterface5=( a) ->  a + 100;

        //如果形参只有一个参数的数据类型和()括号都可以省略不写
        MyInterface3 myInterface6=a ->  a + 100;

    }
}

快速生成Lambda表达式的方法:

先写成匿名内部类。然后你按alt+enter一提示,可以让IDEA给你转换成Lambda表达式

Lambda表达式的使用限制
Lambda表达式的使用限制:Lambda表达式,需要函数式接口的支持。
函数式接口:这个接口中,只有一个抽象方法,这种接口我们就称之为函数式接口。
有一个注解 @FunctionalInterface 可以检测这个接口是不是一个函数式接口

JDK1.8之后,他提供了很多的函数式接口来作为参数传递。

举例:Consumer接口


import java.util.function.Consumer;

public class MyTest2 {
    public static void main(String[] args) {
        //JDK1.8之后,他提供了很多的函数式接口。来作为参数传递。

        Consumer consumer = new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        };
        Consumer consumer2=o-> System.out.println(o);

    }
}

方法引用

方法引用其实是对Lambda表达式的进一步简写

先看一个例子


public class MyTest1 {
    public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("hello");

        System.out.println("=============");
        Consumer<String> consumer2=x-> System.out.println(x);
        consumer2.accept("hello2222");

        System.out.println("============");
		//方法引用
        Consumer<String> consumer3=System.out::println;
        consumer3.accept("hello33333");

    }
}

方法引用:对接口中的抽象方法 public void accept(String s) 的具体实现逻辑,就是System.out.println(x);
观察接口中的抽象方法 accept(String s) 这个抽象方法 返回值是void ,也是有一个参数。而这个抽象方法的具体实现,System.out.println(x); 实现逻辑是用了一个对象PrintStream调用了一个println(x)方法,那么println(x)观察发现,这个方法返回值也是void ,也是一个参数。
那么println(x)方法的返回值和参数列表 正好跟重写的这个accept(String s)方法的返回值和参数列表个数一致,那么就可以使用方法引用进行简写
方法引用的第一种语法是 对象::实例方法

例子:


public class MyTest2 {
    public static void main(String[] args) {
        Consumer consumer2= x->{
            PrintStream out = System.out;
            out.println(x);
        };
        consumer2.accept("hello22222");

        System.out.println("===============");
        Consumer consumer3=System.out::println;
        consumer3.accept("hello3");
   }
}

方法引用的第二种语法是 类名::静态方法


public class MyTest3 {
    public static void main(String[] args) {
        BinaryOperator<Double> binaryOperator = new BinaryOperator<Double>(){

            @Override
            public Double apply(Double a, Double b) {
                double max = Math.max(a, b);
                return max;
            }
        };

        System.out.println("===================");

		//使用Lambda表达式进行简写
        BinaryOperator<Double> binaryOperator1 = (a, b) -> Math.max(a, b);

        System.out.println("=======================");


        //类名::静态方法
        BinaryOperator<Double> binaryOperator2=Math::max;
        Double apply = binaryOperator2.apply(5.0, 20.0);
        System.out.println(apply);

    }
}

方法引用的第三种语法是 类名::实例方法

使用这种方式进行方法引用简写时,有一个特点,在重写接口中的方法中,传入的两个参数。一个参数作为了调用者,一个参数作为了传入者。

看一个例子:



public class MyTest6 {
    public static void main(String[] args) {
        Comparator<String> stringComparator = new Comparator<String>(){
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        };

        System.out.println("================");
        Comparator<String> comparator=(s1,s2)->s1.compareTo(s2);

        System.out.println("================");
        //方法引用: 类名::实例方法
        //我们重写接口中的方法,传入的两个参数。一个参数作为了调用者,一个参数作为了传入者。
        Comparator<String> comparator2=String::compareTo;
    }
}

构造引用
对抽象方法get() 的重写逻辑是 用new 调用了一个空参构造方法   Student()
这个空参构造方法 Student() 没有参数,而且new完之后,会返回一个对象了
正好和 get() 方法的 参数列表和返回值类型能对应上,那么就可以使用构造引用

看一个例子:找一个函数式接口,这个接口中的抽象方法没有形参, 这个方法有一个泛型返回值。这时就可以使用空参的构造引用

构造引用的语法: 类名::new


public class MyTest1 {
    public static void main(String[] args) {
        Supplier<Student> supplier = new Supplier<Student>() {
            @Override
            public Student get() {
                return new Student();
            }
        };
  
        System.out.println("==================");

        //构造引用
        Supplier<Student> supplier2=Student::new;
    }
}

当使用有参的构造引用时,找一个函数式接口,这个接口中的抽象方法要两个参数 ,同时这个方法还得有一个返回值。

BiFunction<T, U, R> T是方法的第一个形参类型,U是方法的第二个形参类型 R是方法的返回 值类型

有参的构造引用的语法和无参的一样,也是:类名::new

public class MyTest2 {
    public static void main(String[] args) {
        BiFunction<String, Integer, Student> biFunction = new BiFunction<String, Integer, Student>() {
            @Override
            public Student apply(String name, Integer age) {
                return new Student(name, age);
            }
        };
        Student student = biFunction.apply("张三", 23);

        System.out.println("=================");
        //使用构造引用进行简化
        BiFunction<String, Integer, Student> biFunction1=Student::new;
  		Student student = biFunction1.apply("张三", 23);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值