Lambda表达式,内置函数式接口

1. Lambda表达式概述

 Java 8 新特性

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

Lambda表达式用于创建匿名函数,可以在需要函数对象的任何地方使用它们。

Lambda表达式的基本语法是:lambda arguments: expression,其中:

  • arguments是逗号分隔的参数列表,类似于函数定义中的参数列表。
  • expression是执行函数体的表达式。

例如,下面的代码展示了如何使用lambda表达式来定义一个简单的函数并调用它:

add = lambda x, y: x + y
result = add(3, 4)
print(result) # 输出 7

还可以将lambda表达式作为参数传递给其他函数,例如map()filter(),可以将其用于列表,元组或其他序列的操作,如下所示:

numbers = [1, 2, 3, 4, 5]
squares = map(lambda x: x**2, numbers)
filtered = filter(lambda x: x > 3, numbers)
print(list(squares)) # 输出 [1, 4, 9, 16, 25]
print(list(filtered)) # 输出 [4, 5]

Lambda表达式还可以用于排序,比较或任何需要函数对象的场合。通过以上方法使用Lambda表达式,可以更加灵活地编写代码,提高代码的简洁性和可读性。

使用 Lambda 表达式可以使代码变的更加简洁紧凑.

Lambda 表达式(lambda expression)是一个匿名函数,简单来说,Lambda表达式是一个可传递的代码段。可以不借助对象传递的一个代码段。

2.1 简述lambda的由来

package demo01;

public class Test01 {
    public static void main(String[] args) {
        //开启一个线程 该构造函数需要传递一个Runnable类型的接口参数
        Thread thread = new Thread(new My());
        thread.start();//开启线程
        //匿名内部类
        Thread thread1=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("通过匿名内部类实现线程任务");
            }
        });
        thread1.start();//开启线程

    }
}
class My implements  Runnable{

    @Override
    public void run() {
        System.out.println("使用实现类来完成------->线程任务");
    }
}

分析:

  1. Thread类需要一个Runnable接口作为参数,其中的抽象方法run方法是用来指定线程任务内容的核心

  2. 为了指定run方法体,不得不需要Runnable的实现类.

  3. 为了省去定义一个Runnable 的实现类,不得不使用匿名内部类.

  4. 必须覆盖重写抽象的run方法,所有的方法名称,方法参数,方法返回值不得不都重写一遍,而且不能出错.

  5. 而实际上,只在乎方法体中的代码.

  6. 可以使用lambda表达式来完成上面的功能。

2.2 简单的lambda表达式。

 //lambda表达式.
        Runnable runnable1=()->{
            System.out.println("这是lambda表达式完成线程任务");
        };
        Thread thread2=new Thread(runnable1);
        thread2.start();

2.3 lambda表达式的语法

Lambda省去了面向对象的条条框框,Lambda的标准格式由3个部分组成:

(参数列表)->{}
():参数列表
->:连接符 连接的是参数以及方法体。
{}: 方法体。

2.4 无参无返回值的Lambda

package demo02;

public class Test02 {
    public static void main(String[] args) {
        //主函数调用fun方法。
        //第一种:创建UserService接口的实现类,并创建该实现类对象。
        //第二种: 匿名内部类的方式
        //  UserService userService=new UserService() {
        //      @Override
        //      public void show() {
        //         System.out.println("这是匿名内部类的show方法的实现");
        //     }
        //  };
        //  fun(userService);
        //第三种lambda表达式:--该接口必须为函数式接口
         UserService userService=()->{
             System.out.println("lambda表示的show方法");
         };
         fun(userService);
    }
    public static void fun(UserService userService){//UserService userService=
        userService.show();
    }
}
//函数式接口-->里面有且仅有一个抽象方法。--只有这种接口才能使用lambda表达式。
interface UserService{
    public void show();
}

2.5 有参有返回值。

package demo03;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class Test03 {
    public static void main(String[] args) {
        List<Person> personList=new ArrayList<>();
        personList.add(new Person("张三",15));
        personList.add(new Person("李四",5));
        personList.add(new Person("王五",65));
        personList.add(new Person("赵六",45));
        personList.add(new Person("田七",35));
        //对集合中的元素按照年龄排序。小到大
        System.out.println(personList);
        //Collections:集合工具类。--匿名内部类
//        Comparator<Person> comparator=new Comparator<Person>() {
//            @Override //如果是0表示相同 大于0表示o1大于02
//            public int compare(Person o1, Person o2) {
//                return o1.getAge()-o2.getAge();
//            }
//        };
//        Collections.sort(personList,comparator);
//        System.out.println(personList);
        Comparator<Person> comparator=(o1,o2)->{ 
            //就是对函数式接口中抽象方法的简写。
          return o1.getAge()-o2.getAge();
        };
          Collections.sort(personList,comparator);
          System.out.println(personList);
    }
}
class Person{
     private String name;
     private Integer age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.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;
    }
}

2.6 Lambda表达式的省略写法

在lambda表达式的标准写法基础上,可以使用省略写法的规则为:

  1. 小括号内的参数类型可以省略[ ]

  2. 如果小括号内有且仅有一个参数,则小括号可以省略

  3. 如果大括号内有且仅有一个语句,可以同时省略大括号,return 关键字及语句分号。

package demo04;

public class Test05 {
    public static void main(String[] args) {
        USB u=(str)-> str.toUpperCase();//lambda表达式:
//        USB u=new USB() {//匿名内部类对接口中抽象方法的个数没有任何要求.
//            @Override
//            public String toUpper(String str) {
//                return null;
//            }
//
//            @Override
//            public String toLower(String str) {
//                return null;
//            }
//        };
        fun(u);
    }
    public static void fun(USB usb){
        String s = usb.toUpper("hello");
        System.out.println(s);
    }
}
interface USB{
    public String toUpper(String str);
//    public String toLower(String str);
}

2.7 Lambda表达式使用的前提

 Lambda表达式的语法是非常简洁的,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意

  1. 方法的参数或局部变量类型必须为接口才能使用Lambda

  2. 接口中有且仅有一个抽象方法(@FunctionalInterface)

  3. 后面我们使用lambda表达式主要核心使用再Stream流中。

3. 内置函数式接口

要想使用lambda表达式它的前提就是必须是函数式接口。

3.1 内置函数式接口的由来

package demo05;


public class Test {

    public static void main(String[] args) {
           Operation o=arr->{
               int sum=0;
               for(int s:arr){
                   sum+=s;
               }
               return sum;
           };
            fun(o);
    }
    public static void fun(Operation operation){
        int[] arr={1,2,3,4};
        int s = operation.getSum(arr);
        System.out.println("数组的和:"+s);
    }
}
@FunctionalInterface
interface Operation{
     public int getSum(int[] arr);
}

分析:

我们知道使用Lambda表达式的前提是需要有函数式接口,而Lambda表达式使用时不关心接口名,抽象方法名。只关心抽象方法的参数列表和返回值类型。因此为了让我们使用Lambda表达式更加的方便,在JDK中提供了大量常用的函数式接口. 大多数无需自己再定义函数式接口,而可以直接使用jdk内置的函数式接口。分成四类。

 3.2 消费型函数式接口Consumer

适合有参数,但是没有返回值的。

public class Test06 {
    public static void main(String[] args) {
        Consumer<Double> c=t->{
            System.out.println("今天洗脚花费:"+t+"元");
        };
        fun(c,200.0);
    }
    public static void fun(Consumer<Double> consumer,Double money){
          consumer.accept(money);
    }
}

3.3 供给型函数式接口---Supplier

无参,需要返回值的接口类。

package demo06;

import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Supplier;


public class Test06 {
    public static void main(String[] args) {
//        Consumer<Double> c=t->{
//            System.out.println("今天洗脚花费:"+t+"元");
//        };
//        fun(c,200.0);
         Supplier<Integer> s=()-> new Random().nextInt(10);
         fun2(s);
    }
    public static void fun2(Supplier<Integer> supplier){
        Integer a = supplier.get();
        System.out.println("结果:"+a);
    }


    public static void fun(Consumer<Double> consumer,Double money){
          consumer.accept(money);
    }
}

3.3 函数型函数式接口---Function<T,R>

T: 参数的泛型

R:返回值的泛型。

package demo05;

import java.util.function.Function;


public class Test {

    public static void main(String[] args) {
           Function<int[],Integer> o=arr->{
               int sum=0;
               for(int s:arr){
                   sum+=s;
               }
               return sum;
           };
            fun(o);
    }
    public static void fun(Function<int[],Integer> fun){
        int[] arr={1,2,3,4};
        int s = fun.apply(arr);
        System.out.println("数组的和:"+s);
    }
}

3.4 断言型函数式接口--Predicate

T: 参数

boolean:返回值类型。

package demo06;

import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;


public class Test06 {
    public static void main(String[] args) {
//        Consumer<Double> c=t->{
//            System.out.println("今天洗脚花费:"+t+"元");
//        };
//        fun(c,200.0);
//         Supplier<Integer> s=()-> new Random().nextInt(10);
//         fun2(s);
//          Function<String,String> fun=t->t.toUpperCase();
//          fun3(fun,"hello world");
          Predicate<String> p=t->t.length()>3;
          fun4(p,"欧阳锋"); //4
    }

    public static void fun4(Predicate<String> predicate,String name){
        boolean test = predicate.test(name);
        System.out.println("是否成年:"+test);
    }

    public static void fun3(Function<String,String> f,String str){
        String apply = f.apply(str);
        System.out.println("结果:"+apply);
    }
    public static void fun2(Supplier<Integer> supplier){
        Integer a = supplier.get();
        System.out.println("结果:"+a);
    }

    public static void fun(Consumer<Double> consumer,Double money){
          consumer.accept(money);
    }
}

4. 方法引用

特殊的lambda表达式,它是对lambda表达式的一种简写方式。

4.1 方法引用的由来

package demo07;

import java.util.function.Consumer;

public class Test07 {
    public static void main(String[] args) {
           Consumer<int[]> c=t->{
                int sum=0;
                for(int a:t){
                    sum+=a;
                }
               System.out.println("数组的和:"+sum);
           };
           fun(c);
    }
    public static void fun(Consumer<int[]> consumer){
          int[] arr={1,2,3,4,5};
          consumer.accept(arr);
    }

    //求和方法
    public static void sum(int[] arr){
        int sum=0;
        for(int a:arr){
            sum+=a;
        }
        System.out.println("数组的和:"+sum);
    }
}

如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过去就好了:---方法引用。::

package demo07;

import demo01.AAA;

import java.util.function.Consumer;

public class Test07 {
    public static void main(String[] args) {
//           Consumer<int[]> c=t->{
//                int sum=0;
//                for(int a:t){
//                    sum+=a;
//                }
//               System.out.println("数组的和:"+sum);
//           };
//        Consumer<int[]> c=(t)->Test07.sum(t); //
           Consumer<int[]> c= Test07::sum;
           fun(c);
    }
    public static void fun(Consumer<int[]> consumer){
          int[] arr={1,2,3,4,5};
          consumer.accept(arr);
    }

    //求和方法
    public static void sum(int[] arr){
        int sum=0;
        for(int a:arr){
            sum+=a;
        }
        System.out.println("数组的和:"+sum);
    }
}

4.2 方法引用的类型

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值