目录
(1)Lambda表达式:特殊的匿名内部类,语法更简洁。
(2)Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。
基本语法
<函数式接口> <变量名>=(参数1,参数2...)->{
//方法体
};
注意: 函数式接口:接口中只有一个抽象方法。
(参数1,参数2): 抽象方法的参数
->: 分隔符
{}:表示抽象方法的实现
Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心
为了指定 run 的方法体,不得不需要 Runnable 接口的实现类
为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类
必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错
而实际上,似乎只有方法体才是关键所在。
这时可以使用lambda表示完成上面的要求。
前提:必须是函数式接口。
简化匿名内部类的使用,语法更加简单。
总代码展示:
- public class LambdaTest {
- public static void main(String[] args) {
- My m=new My();
- Thread t1=new Thread(m);
- t1.start();
-
- Thread t2=new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("匿名函数式");
- }
- });
- t2.start();
-
- Runnable t3=()->{
- System.out.println("lambda表达式");
- };
- Thread t03=new Thread(t3);
- t03.start();
-
- Thread t4=new Thread(()->{
- System.out.println("lambda精简表达式");
- });
- t4.start();
- }
- }
- class My implements Runnable{
-
- @Override
- public void run() {
- System.out.println("Runnable方法");
- }
- }
代码展示:
- public class WuCanWuFan {
- public static void main(String[] args) {
- Swimming swimming=new Swimming() {
- @Override
- public void swim() {
- System.out.println("小明在游泳");
- }
- };
- fun(swimming);
-
- System.out.println("================lambda=========================");
-
- // Swimming swimming1=()->{
- // System.out.println("小花在游泳");
- // };
- fun(()->{
- System.out.println("小花在游泳");
- });
- }
-
- public static void fun(Swimming swimming){
- swimming.swim();
- }
- }
- interface Swimming{
- public void swim();
- }
举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:
public abstract int compare(T o1, T o2);
当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。
代码展示:
- public class Compable {
- public static void main(String[] args) {
- List
people=new ArrayList<>(); - people.add(new Person("张三",15,185));
- people.add(new Person("李四",23,179));
- people.add(new Person("王五",8,145));
- people.add(new Person("赵六",34,180));
-
- //对集合中的元素进行排序 按照年龄从小到大
- //传统做法:Comparator:排序规则接口
- Comparator
comparator=new Comparator() { - //int : 0表示新加的元素和集合中的元素是相等的
- //1表示新加的元素比集合中的元素大
- //-1表示新加的元素比集合中的元素小
- @Override
- public int compare(Person o1, Person o2) {
- return o2.getAge()- o1.getAge();
- }
- };
- Collections.sort(people,comparator);
- for (Person p:people) {
- System.out.println(p);
- }
-
- System.out.println("===============================lambda===============================");
-
- Comparator
comparator1=(Person o1,Person o2)->{ - return o1.getAge()- o2.getAge();
- };
-
- Collections.sort(people,comparator1);
- for (Person p:people) {
- System.out.println(p);
- }
-
- }
- }
- class Person{
- private String name;
-
- private Integer age;
-
- private Integer tall;
-
- public Person() {
- }
-
- public Person(String name, Integer age, Integer tall) {
- this.name = name;
- this.age = age;
- this.tall = tall;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- public Integer getTall() {
- return tall;
- }
-
- public void setTall(Integer tall) {
- this.tall = tall;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", tall=" + tall +
- '}';
- }
- }
注意事项 :
形参列表的数据类型会自动推断
如果形参列表为空,只需保留()
若形参只有一个,()可以省略,只需要参数的名称即可(此题证明)
如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则想省去{},则必须同时省略return,且执行语句也保证只有一句
Lambda不会生成一个单独的内部类文件
- public class NoticeTest {
- public static void main(String[] args) {
-
- fun(n->{
- System.out.println(n+"正在玩手机");
- });
- }
-
- public static void fun(Plays plays){
- plays.play("小明");
- }
- }
- interface Plays{
- public void play(String name);
- }
我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽 象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。
常见的函数式接口:java.util.function保存

如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambdda表达式会被匹配到这个抽象方法上。
@Functionallnterface注解检测接口是否符合函数式接口。
- public class Test03 {
-
- public static void main(String[] args) {
- Operater o=arr -> {
- int sum=0;
- for(int n:arr){
- sum+=n;
- }
- System.out.println("数组的和为:"+sum);
- };
-
- fun(o);
- }
-
- public static void fun(Operater operater){
- int[] arr={2,3,4,5,6,7,11};
- operater.getSum(arr);
- }
-
- }
- @FunctionalInterface
- interface Operater{
- //求数组的和
- public abstract void getSum(int[] arr);
- }
消费型函数 :有参无返回值
举例:去美甲店消费一次的开销
- public class ConsumerTest {
- public static void main(String[] args) {
-
- Consumer
consumer=t->{ - System.out.println("美甲花了:"+t);
- };
- fun(consumer,200);
-
- }
- //调用某个方法时,该方法需要的参数为接口类型,这时就应该能想到使用lambda
- public static void fun(Consumer
consumer, double money) { - consumer.accept(money);
- }
- }
举例:遍历数组和
- public class ConsumerTest02 {
- public static void main(String[] args) {
- getSum(t->{
- int sum=0;
- for (int i:t) {//此处遍历t即代表arr
- sum+=i;
- }
- System.out.println(sum);
- },new int[]{1,2,3,4,5});
- }
- public static void getSum(Consumer<int[]> consumer, int[] arr){//注意Consumer
- consumer.accept(arr);
-
- }
- }
T表示返回结果的泛型 :无参有返回值的函数式接口
举例:随机获取0到10之间的数字
- public class SupplierTest {
- public static void main(String[] args) {
- getNumber(()->{
- return new Random().nextInt(10);
- });
- }
- public static void getNumber(Supplier
supplier) { - Integer integer = supplier.get();
- System.out.println("获取数字为:"+integer);
- }
- }
有参,有返回值
T:参数类型的泛型
R:函数返回结果的泛型
举例:将字符串转大写
- public class FunctionTest {
- public static void main(String[] args) {
-
- getUpper(t->{
- return t.toUpperCase(Locale.ROOT);//所传参数随便写
- },"hello world");
- }
- public static void getUpper(Function
function,String str) { - String apply = function.apply(str);
- System.out.println("结果为:·"+apply);
- }
- }
举例:计算字符串长度
- public class FunctionTest02 {
- public static void main(String[] args) {
- getLength(t->{
- return t.replace(" ","").length();
- },"hello world");
- }
- public static void getLength(Function
function,String str) { - Integer apply = function.apply(str);
- System.out.println("长度为:"+apply);
- }
- }
boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型
举例:判断名字是否过长
- public class PredicateTest {
- public static void main(String[] args) {
-
- getNameLength(t->{
- return t.length()>3?true:false;
- },"迪丽热巴.迪力木拉提");
- }
- public static void getNameLength(Predicate
predicate,String name) { - boolean test = predicate.test(name);
- System.out.println("名字长度是否超过3:"+test);
- }
- }
如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过来就好了---方法引用
请注意其中的双冒号 :: 写法,这被称为“方法引用”,是一种新的语法
举例:计算数组和
- public class PullIn {
- public static void getSum(int[] arr){
- int sum=0;
- for (Integer i:arr) {
- sum+=i;
- }
- System.out.println("数组和为:"+sum);
- }
- public static void sum(Consumer<int[]> consumer){
- int[] arr={1, 2, 3, 4, 5};
- consumer.accept(arr);
- }
-
- public static void main(String[] args) {
- //此处与上述getSum方法一模一样,造成冗余
- // sum(arr->{
- // int sum=0;
- // for (Integer i:arr) {
- // sum+=i;
- // }
- // System.out.println("数组和为:"+sum);
- // },new int[]{1, 2, 3, 4, 5});
- sum(PullIn::getSum);
- }
- }
方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体只是调用一个特定的已经存在的方法,则可以使用方法引用。
常见形式:
(1)对象::方法名
(2)类名::静态方法
(3)类名::普通方法
(4)类名::new 调用的构造器
(5)String[]::new 调用数组的构造器

注意:
1.被引用的方法,参数要和接口中的抽象方法的参数一样
2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
举例:获取当前时间
- public class PullInTest01 {
- //对象::实例方法
- public static void main(String[] args) {
- Date d=new Date();
- // Supplier
time=()->{ - // return d.getTime();
- // };
- //使用方法引用
- Supplier
time=d::getTime; - //注意:
- //1.被引用的方法,参数要和接口中的抽象方法的参数一样
- //2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
-
- Long aLong = time.get();
- System.out.println("aLong = "+aLong);
- }
- }
举例:获取当前时间
- public class PullInTest02 {
- //类名::静态方法
- public static void main(String[] args) {
- // Supplier
su=()->{ - // return System.currentTimeMillis();
- // };
- Supplier
su=System::currentTimeMillis; -
- Long aLong = su.get();
- System.out.println("aLong="+aLong);
- }
- }
(注意:类名::实例方法实际上会将第一个参数作为方法的调用者)
举例:字符串长度及截取字符串
- public class PullInTest03 {
- public static void main(String[] args) {
- //类名::实例方法(注意:类名::实例方法实际上会将第一个参数作为方法的调用者)
- // Function
f1=(String str)->{ - // return str.length();
- // };
- Function
f1=String::length; -
- Integer hello = f1.apply("hello");
- System.out.println("字符串长度为:"+hello);
-
- //BiFunction
f2=String::substring; - //相当于这样的Lambda
- BiFunction
f2=(String str,Integer index)->{ - return str.substring(index);
- };
- String helloworld = f2.apply("helloworld", 3);
- System.out.println(helloworld);
- }
-
-
- }
举例:person介绍
Person类
- public class Person {
- private String name;
-
- private Integer age;
-
- public Person() {
- System.out.println("调用无参构造");
- }
-
- public Person(String name, Integer age) {
- System.out.println("调用有参构造"+name+"---"+age);
- this.name = name;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
- }
测试类
- public class PullTest04 {
- //类名::new 引用类的构造器
- public static void main(String[] args) {
- // Supplier
su=()->{ - // return new Person();
- // };
- Supplier
su=Person::new; - Person person = su.get();
- System.out.println(person);
-
- // BiFunction
bif=(String name,Integer age)->{ - // return new Person(name,age);
- // };
- BiFunction
bif=Person::new; - Person name = bif.apply("小明", 18);
- System.out.println(name);
- }
- }
举例:数组存放
- public class PullInTest05 {
- //类型【】::new
- public static void main(String[] args) {
-
- // Function
f1=(Integer length)->{ - // return new int[length];
- // };
- Function
int[]> f1=int[]::new; - int[] apply = f1.apply(10);
- System.out.println(Arrays.toString(apply));
- }
- }