首页 > 其他分享 >Lambda表达式

Lambda表达式

时间:2023-12-06 10:45:29浏览次数:21  
标签:System 接口 println Lambda public 表达式 out

目录

1、Lambda表达式概述

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

首先来看一下什么是Lambda表达式:

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        Integer[] ints = {98, 243, 35, 13, 57, 243};
        List<Integer> list = Arrays.asList(ints);    
        //之前的排序
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println(list);
        //[243, 243, 98, 57, 35, 13]

        //使用Lambda表达式
        list.sort((o1,o2)->(o1-o2));

        System.out.println(list);
        //[13, 35, 57, 98, 243, 243]
	}
}

通过上面的对比,发现Lambda表达式式书写起来更为简洁;

2、Lambda表达式语法

JDK1.8之后引入的一种语法,他的写法是使用一个->符号,箭头将Lambda表达式分为左右两部分,左边写的是实现的这个接口中的抽象方法中的形参列表,右边就是对抽象方法的处理;

实现的这个接口中的抽象方法中的形参列表 -> 抽象方法的处理

3、具体写法

因为Lambda表达式的核心就是实现的这个接口中的抽象方法中的形参列表 -> 抽象方法的处理,因此根据形参列表与返回值的不同,Lambda表达式的具体写法也不相同;

无返回值有形参的抽象方法

public class MyTest1 {
    public static void main(String[] args) {
        MyInterface myInterface = new MyInterface() {
            @Override
            public void show(int a, int b) {
                System.out.println(a + b);
            }
        };
		myInterface.show(20, 30);//50

        //简写1:方法名可以自己推断出来
        MyInterface myInterface1 = (int a, int b) -> {
            System.out.println(a + b);
        };

        myInterface1.show(20, 40);//60

        //简写2:可以省略形参列表中的形参类型
        MyInterface myInterface2 = (a, b) -> {
            System.out.println(a + b);//70
        };

        myInterface2.show(20, 50);

        //简写3:如果抽象方法中只有一行代码,可以省略方法体的大括号,当然,如果不止一行,就不能省略
        MyInterface myInterface3 = (a, b) -> System.out.println(a + b);
        myInterface3.show(20, 60);//80
	}
}
public interface MyInterface {
    public abstract void show(int a,int b);
}

可以省略方法名,IDEA会帮你自动检测方法名;
可以省略方法中的形参类型;
如果对抽象方法的实现逻辑只有一行,可以省略方法体的大括号,当然如果不止一行,就不能省略了;

有返回值的抽象方法

public class MyTest2 {
    public static void main(String[] args) {
        MyInterface1 test1 = new MyInterface1() {
            @Override
            public int test(int a, int b) {
                return a - b;
            }
        };
        System.out.println(test1.test(90, 8));//82
        //简写1:
        MyInterface1 test2 = (int a, int b) -> {
            return a - b;
        };
        System.out.println(test2.test(20, 10));//10

        //简写2:
        MyInterface1 test3 = (a, b) -> {return a - b;};
        System.out.println(test3.test(30, 10));//20

        //简写3:这个有返回值的方法,不能直接去掉大括号,还需要去掉return关键字
        MyInterface1 test4 = (a, b) -> a - b;
        System.out.println(test4.test(40, 10));//30
    }
}
public interface MyInterface1 {
    public abstract int test(int a,int b);
}

有返回值的方法,如果要去掉大括号,还需要去掉return关键字;

有一个形参的抽象方法

public class MyTest3 {
    public static void main(String[] args) {
        MyInterface2 myInterface = a -> a-20;
        myInterface.show(20);
    }
}
public interface MyInterface2 {
    public abstract int show(int a);
}

形参列表中只有一个参数,可以去掉形参的括号;
Lambda表达式作为参数传递

import java.util.Arrays;
public class MyTest4 {
    public static void main(String[] args) {
        Integer[] ints = {89, 67, 23};
        Arrays.sort(ints, (o1, o2) -> o1-o2);
        System.out.println(Arrays.toString(ints));
        //[23, 67, 89]
    }
}

Lambda表达式也可以作为参数传递;

4、Lambda表达式注意事项

  • Lambda表达式不是万能的,他需要函数式接口的支持;
    什么是函数式接口
    函数式接口的定义是: 只包含一个抽象方法的接口,称为函数式接口;
    其实我们的Lambda表达式就是对函数式接口的一种简写方式,所以只有是函数式接口,我们才能用Lambda表达式;再换句话说,Lambda表达式需要函数式接口的支持,那函数式接口我们可以自己定义,当然JDK1.8也给我们提供了一些现成的函数式接口;

    //自定义一个函数式接口
    @FunctionalInterface //此注解用来表明这是一个函数式接口
    public interface MyInterface<T> {
        //函数式接口只能有一个抽象方法
        void getValue(T t);
    }
    MyInterface<String> face = (x)->System.out.println(x);
    
  • 可以通过 Lambda 表达式来创建该接口的对象,我们可以在任意函数式接口上使用@FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口;

  • 为什么只能有一个抽象方法,如果有多个抽象方法,这个接口不是函数式接口,简写的时候省略了方法名,IDEA不能知道到底重写的是哪一个方法,不能推断出来;

  • 注解写在接口声明上面,如果不报错,就不是函数式接口;

  • JDK1.8之后,提供了很多函数式接口,作为参数传递;

5、Java中四大函数式接口

6、方法引用

先来看一下什么是方法引用:

  • 方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;
    注意: 实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
    方法引用:使用操作符::将方法名和对象或类的名字分隔开来,三种主要使用情况为:

    对象::实例方法
    ::静态方法
    ::实例方法

    对象::实例方法

import java.util.function.Consumer;

public class MyTest {
    public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("aaaaaaaaaaaaaa");
        //aaaaaaaaaaaaaa
        //简写1:
        Consumer<String> consumer1 = (String s) -> {
            System.out.println(s);
        };
        consumer1.accept("abc");
        //abc

        //简写2:
        Consumer<String> consumer2 = (s) -> System.out.println(s);
        consumer2.accept("bcd");
        //bcd

        //简写3:
        Consumer<String> consumer3 = System.out::println;
        consumer3.accept("abc");
        //abc
    }
}

为什么可以写成上述方式?
因为:System.out.println(s);与void accept(String s)一样,都是使用s作为参数,返回值是void,因此就可以简写为简写3;

::静态方法

import java.util.function.BinaryOperator;

public class MyTest1 {
    public static void main(String[] args) {
        BinaryOperator<Double> operator = new BinaryOperator<Double>(){
            @Override
            public Double apply(Double o, Double o2) {
                return Math.max(o,o2);
            }
        };
        System.out.println(operator.apply(2.13, 3.12));//3.12

        BinaryOperator<Double> operator2 = (o, o2) -> Math.max(o,o2);
        System.out.println(operator2.apply(2.13, 3.12));//3.12

        BinaryOperator<Double> operator3 = Math::max;

        Double max = operator3.apply(5.0, 20.0);
        System.out.println(max);//20.0
    }

}

因为Math.max()所需要的参数以及返回值与重写的accpet()一样,因此可以简写为类::静态方法;

import java.util.Comparator;
public class MyTest2 {
    public static void main(String[] args) {
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        System.out.println(comparator.compare(20, 12));//1

        Comparator<Integer> comparator1 = Integer::compareTo;
        System.out.println(comparator1.compare(20, 12));//1
    }
}

类::实例方法

import java.util.Comparator;
public class MyTest2 {
    public static void main(String[] args) {
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        };
    System.out.println(comparator.compare("20", "12"));//1

    Comparator<String> comparator1 = String::compareTo;
    System.out.println(comparator1.compare("20", "12"));//1
}

为什么可以这样写?、
传递过来的两个参数,一个作为调用者,一个作为参数,这时候,使用类::实例方法简写;

7、构造引用

格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

import java.util.function.Supplier;
public class Mytest3 {
    public static void main(String[] args) {
        Supplier<Student> supplier = new Supplier<Student>() {
            @Override
            public Student get() {
                return new Student();
            }
        };
        Student student = supplier.get();

        Supplier<Student> supplier1 = () -> new Student();
        Student student1 = supplier1.get();
    }
}
public class Mytest3 {
    public static void main(String[] args) {
        Supplier<Student> supplier = new Supplier<Student>() {
            @Override
            public Student get() {
                return new Student("张三",23);
            }
        };
        Student student = supplier.get();
        System.out.println(student);

        Supplier<Student> supplier1 = () -> new Student("李四",25);
        Student student1 = supplier1.get();
        System.out.println(student1);
    }
}
public class MyTest4 {
    public static void main(String[] args) {
        Student student = new Student("张三", 23);
        BiFunction<String, Integer, Student> function = new BiFunction<String, Integer, Student>() {
            @Override
            public Student apply(String s, Integer integer) {
                return student;
            }
        };
        BiFunction<String, Integer, Student> function1 = (s, integer) -> student;

        BiFunction<String, Integer, Student> function2 = Student::new;
    }
}

之所以可以这样简写,是因为构造方法的形参与返回值与重写的方法一样;

标签:System,接口,println,Lambda,public,表达式,out
From: https://www.cnblogs.com/codeli/p/17878982.html

相关文章

  • 三元表达式、列表、字典生成式和匿名函数
    一、三元表达式1、引入比价两个数的大小,正常函数写法defmy_max(a,b):ifa>b:returnaelse:returnbmy_max(1,2)2、三元表达式写法defmy_max(a,b):returnaifa>belsebres=my_max(1,2)print(res)3、语法结构:条件成立......
  • Optional常用方法实例, 源码挺简单的,重要的是option 与 stream 以及lambda 的连贯使用
    Optionalstaticmethods: Optional.ofNullable();Optional.empty();Optional.of(); ​ empty():publicstatic<T>Optional<T>empty(){@SuppressWarnings("unchecked")Optional<T>t=(Optional<......
  • CEL 表达式
    字符串函数'refs/heads/main'.split('/')//result=list['refs','heads','main']['refs','heads','main'].join('/')//result=string'refs/heads/main'......
  • 动手写一个正则表达式引擎
    曾经有人开玩笑:当碰到棘手问题的时候,可以考虑使用正则表达式当考虑正则表达式的时候,又多了一个棘手的问题日常工作中,正则表达式是一个非常强大的工具,编写编译器/解释器的时候,正则表达式是必须的工具。自己动手写一个正则表达式,有利于使用者以正则表达式的方式思考,也是一个非常好......
  • Java登陆第十七天——Java8之Lambda表达式
    在实例化Thread类时,需要传入一个Runnable接口的实现类。publicThread(Runnabletarget)实际开发中,通常是使用匿名内部类实现Runnable接口。栗子:publicclassTest27{publicstaticvoidmain(String[]args){Threadt=newThread(newRunnable(){//匿名......
  • Java登陆第十七天——正则表达式
    在java.util.regex包下,提供了正则表达式对字符串进行约束规范匹配正则表达式必须依靠Pattern类和Matcher类。PatternPattern类的主要作用是编写正则规范。常用方法如下:方法类型描述publicstaticPatterncompile(Stringregex)静态方法传入正则表达式规则,并返回......
  • AcWing 3302. 表达式求值
    题面:给定一个表达式,其中运算符仅包含加减乘除,可能包含括号,请你求出表达式的最终值。原题链接:3302.表达式求值-AcWing基本思路创建两个栈,分别存储数字和运算符运算符的判定:仅在以下条件满足时将运算符直接压入栈中:①栈中不存在元素②当前运算符优先级比栈顶高③栈顶为......
  • 【算法】远方来信,从数学表达式算法到汇编语法解释器
    在繁华的都市中,小悦作为一名软件工程师,每天都在这座钢筋水泥的森林里忙碌。她的生活似乎被工作和各种琐碎的事情填满了,但在这个繁忙的生活中,她总能在工作之余找到一些小小的乐趣。这天下班后,小悦收到了一封来自国外同学苏菲的email。邮件的内容让她的思绪一下子飘回了那个学习汇......
  • python 正则表达式总结
    python正则表达式总结#findall找出所有的,match从第一个字符开始找,fullmatch全句完全匹配,search从任意位置开始找text="jack最好,jack最好的,jack最好了,jack是最好的"pattern="jack最好"print(re.findall(pattern,text))输出:['jack最好',......
  • 【Linux 基础】正则表达式 与 通配符 区别
    简短不看版:通配符和正则表达式比较(1)通配符和正则表达式看起来有点像,不能混淆。可以简单的理解为通配符只有*,?,[],{}这4种,而正则表达式复杂多了。(2)*在通配符和正则表达式中有其不一样的地方,在通配符中*可以匹配任意的0个或多个字符,而在正则表达式中他是重复之前的一个或者多个......