Java中的Lambda表达式和相关函数式接口

知识模块:
一.Lambda表达式概述:
二.Lambda表达式使用前提
三.Lambda表达式
        一.完整格式
        二.简略格式
四.Lanbda表达式原理
五.Java中已有的函数式接口
        a.Supplier
        b.Consumer接口
        c.Function
        d.Predicate






一.Lambda表达式概述:
   面向对象编程思想关注如何创建一个类的对象,然后通过这个类的对象调用类中的成员
   面向函数编程思想(函数式编程)更关注函数的使用或者说更关注最终实现目标,从而简化代码
   Lambda表达式就是为了实现函数式编程
二.Lambda表达式使用前提
   1.每个Lambda表达式都对应一个接口,并且只能对应接口类型
   2.该接口中只能含有一个抽象方法(JDK1.8以后,接口中含有默认方法,静态方法)
   JDK1.8及之后引入一个注解 @FunctionalInterface,检测该接口中是否只有一个抽象方法
   如果只有一个抽象方法编译通过,否则编译失败

@FunctionalInterface //代表该接口可以用作函数式编程,或者说可以用作Lambda表达式
public interface A {
    void method();

    default void method02() {
        System.out.println("method02方法");
    }

    static void method03() {
        System.out.println("method03方法");
    }
    //void method04();
}
三.Lambda表达式
      /*
      Lambda表达式格式与使用
         interface 接口名{
             返回值类型 方法名(形参列表); //接口中唯一一个抽象方法
         }
         一.完整格式
           (参数类型1 参数名1,参数类型2 参数名2,.....)->{语句1;语句2;....}
           ():小括号的 参数类型 参数名对应接口中抽象方法的形参列表
              如果接口中的抽象方法形参列表为空,那么Lambda表达式的小括号就写{}
           {}:大括号中的语句相当于实现了该类接口中抽象方法的语句
@FunctionalInterface
public interface Calculator {
    int getSum(int a, int b);
}
@FunctionalInterface
public interface Printer {
    void print (String str);
}

/*
Lambda表达式格式与使用
   interface 接口名{
       返回值类型 方法名(形参列表); //接口中唯一一个抽象方法
   }
   一.完整格式
     (参数类型1 参数名1,参数类型2 参数名2,.....)->{语句1;语句2;....}
     ():小括号的 参数类型 参数名对应接口中抽象方法的形参列表
        如果接口中的抽象方法形参列表为空,那么Lambda表达式的小括号就写{}
     {}:大括号中的语句相当于实现了该类接口中抽象方法的语句
   二.简略格式
 */
public class LambdaDemo03 {
    @Test
    public void test01() {
        method("你好Lambda表达式",(String str)->{
            System.out.println(str);});
    }

    public void method(String str, Printer p) {
        p.print(str);
    }

    @Test
    public void test02() {
        method02(3,12,(int a,int b)->{return a + b;});
    }
    public void method02(int a, int b, Calculator c) {
        int sum = c.getSum(a, b);
        System.out.println(sum);
    }
}
         二.简略格式
       */

      /*
         二.简略格式:
           a.省略参数类型
           (参数名)->{语句1;语句2;....} // ()中可以省略参数类型,因为Lambda可以根据代码自动推断类型
           b.省略()
           参数名->{语句1;语句2;...} //当接口中的抽象方法的形参只有一个的时候,Lambda表达式可以省略()
           c.省略{}
           (参数类型1 参数名1,参数类型2 参数名2...)->语句;  //当重写接口中的抽象方法只有一条语句的时候,我们可以省略{}
                                                         //省略{}的同时,也要省略return和 ;
        */

import org.junit.Test;

/*
  二.简略格式:
    a.(参数名)->{语句1;语句2;....} // ()中可以省略参数类型,因为Lambda可以根据代码自动推断类型
    b.参数名->{语句1;语句2;...} //当接口中的抽象方法的形参只有一个的时候,Lambda表达式可以省略()
    c.(参数类型1 参数名1,参数类型2 参数名2...)->语句;  //当重写接口中的抽象方法只有一条语句的时候,我们可以省略{}
                                                  //省略{}的同时,也要省略return和 ;
 */
public class LambdaDemo04 {
    @Test
    public void test01() {
        method("你好", (str) -> {
            System.out.println(str);
        });

        method02(4, 19, (a, b) -> {
            return a + b;
        });
    }

    @Test
    public void test02() {
        method("大家好", str -> {
            System.out.println(str);
        });
    }

    @Test
    public void test03() {
        method("张三丰",str-> System.out.println(str));
        method02(9,12,(a,b)->a+b);
    }


    public void method(String str, Printer p) {
        p.print(str);
    }

    public void method02(int a, int b, Calculator c) {
        int sum = c.getSum(a, b);
        System.out.println(sum);
    }
}
四.Lanbda表达式原理
      /*
       Lambda原理
           类似于匿名内部类的原理
           1.底层会创建Lambda表达式对应的接口的一个实现类
             每个Lambda表达式对应一个实现类,重写的目标对应Lambda表达式{}中的内容
           2.当使用该Lambda表达式的时候,底层给会创建该实现类对象
       */

import lambda03.Printer;
import org.junit.Test;

/*
 Lambda原理
     类似于匿名内部类的原理
     1.底层会创建Lambda表达式对应的接口的一个实现类
       每个Lambda表达式对应一个实现类,重写的目标对应Lambda表达式{}中的内容
     2.当使用该Lambda表达式的时候,底层给会创建该实现类对象
 */
public class LambdaDemo05 {
        @Test
        public void test01() {
            method("你好Lambda表达式", (String str) -> {
                System.out.println(str);
            });
        }
        public void method(String str, Printer p) {
            p.print(str);
        }

    @Test
    public void test02() {
        Printer p = str -> System.out.println(str);
        System.out.println(p);
        for (Class in : p.getClass().getInterfaces()) {
            System.out.println(in);
        }
    }
    @Test
    public void test03() {
        Printer p = str -> System.out.println(str); //相当于 Painter p = new LambdaDemo02$$Lambda$1();//多态
        p.print("abc");
    }
    }


/*
//在程序的运行时期,会生成这个Lambda表达式对应的接口的一个实现类,并且重写接口中的抽象方法,重写的目标对应Lambda表达式{}中的内容
  而且这个可u是一个内部类
public class LambdaDemo05 {
        @Test
        public void test01() {
            method("你好Lambda表达式", new )LambdaDemo02$$Lambda$1();
        }
        public void method(String str, Printer p) {//String str = "你好Lambda表达式"
                                                   //Printer p = new LambdaDemo02$$Lambda$1();
            p.print(str);  //最终相当于是调用实现类中的print(String str)方法
        }

          //在程序的运行时期,会生成这个Lambda表达式对应的接口的一个实现类
        class LambdaDemo02$$Lambda$1 implements Printer{
          //重写抽象方法
           public void printer(String str){
             System.out.println(str);//对应Lambda表达式{}中的内容
           }
        }

    }

 */
import org.junit.Test;

import java.lang.reflect.Method;

/*
 Lambda表达式原理
 */
public class LambdaDemo06 {
    @Test
    public void test02() {
        method02(3,12,(int a,int b)->{return a + b;});
    }
    public void method02(int a, int b, lambda03.Calculator c) {
        int sum = c.getSum(a, b);
        System.out.println(sum);
    }

    @Test
    public void test03() throws NoSuchMethodException {
        Calculator c=(a, b)->a+b;
        System.out.println(c);
        System.out.println(c.getClass());
        for (Class in : c.getClass().getInterfaces()) {
            System.out.println(in);
        }
        Method method = c.getClass().getMethod("getSum", int.class, int.class);
        System.out.println(method);
    }
    @Test
    public void test04() throws NoSuchMethodException {
        Calculator c=(a, b)->a+b; //Calculator c = new LambdaDemo06$$Lambda$1();
        System.out.println(c.getSum(15, 12));
        //(a,b)->a+b.getSum(15,17); //如果这杨写,Lambda表达式无法推断这个getSum(int,int)方法到底是哪个表达式的方法

    }
}
/*

//在运行时,JVM会为这个Lambda表达式对应的接口创建一个实现类
//重写该接口中的抽象方法,重写的目标对应Lambda表达式{}中内容
//该实现类是一个内部类
public class LambdaDemo06 {
    @Test
    public void test02() {
        method02(3,12,new LambdaDemo06$$Lambda$1());
    }


    public void method02(int a, int b, Calculator c) {  //int a=3,int b=12
                                                        //Calculator c = new LambdaDemo06$$Lambda$1()
        int sum = c.getSum(a, b); //int sum=15;
        System.out.println(sum);
    }
    //1.在运行时,JVM会为这个Lambda表达式对应的接口创建一个实现类
    class LambdaDemo06$$Lambda$1 implements Claculator{
    //2.重写该接口中的抽象方法,重写的目标对应Lambda表达式{}中内容
        public int getSum(int a,int b){ //int a=3,int b=12
          return a+b;
        }
    }
}

 */
五.Java中已有的函数式接口
   a.Supplier
         /*
           Supplier接口:
              适用于只获取结果不传递参数的操作

             @FunctionalInterface
         public interface Supplier {


               Gets a result.
               @return a result
             T get();
                     }

         Arrays类中的toString方法
               static String toString(int[] a)
                      将数组中的元素拼接成一个字符串,然后返回这个字符串

          */


import org.junit.Test;

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

/*
  Supplier接口:
     适用于只获取结果不传递参数的操作

    @FunctionalInterface
public interface Supplier {


      Gets a result.
      @return a result
    T get();
            }

Arrays类中的toString方法
      static String toString(int[] a)
             将数组中的元素拼接成一个字符串,然后返回这个字符串

 */
public class SupplierDemo {
    @Test
    public void test01() {
        //获取1~10之间的随机数
        int i = new Random().nextInt(10) + 1;//[1,11)
        System.out.println(i);
    }

    @Test
    public void test02() {
        //Suppliers=()->{return new Random().nextInt(10) + 1;};
        Suppliers=()-> new Random().nextInt(10) + 1;
        System.out.println(s.get());

    }

    @Test
    public void test03() {
    //获取10个1~10之间的随机数,将这些随机数存放到一个数组,最后打印数组中的元素
        int[] arr = new int[10];
        Supplier s = () -> new Random().nextInt(10) + 1;
        for (int i = 0; i < 10; i++) {
            arr[i]=s.get();
        }
        Supplier s2 = () -> Arrays.toString(arr);
        System.out.println(s2.get());

    }
}
/*
   class SupplierDemo$$Lambda$1 implements Supplier{

         public Integer get(){
             return new Random().nextInt(10)+1;
         }

   }


 */
   b.Consumer接口
       /*
         Consumer接口
             一般用于值传递参数消费(执行)而不获取结果的

         public interface Consumer {

            Performs this operation on the given argument.

             @param t the input argument

           void accept(T t);
           }
        */


import org.junit.Test;

import java.util.concurrent.Flow;
import java.util.function.Consumer;

/*
  Consumer接口
      一般用于值传递参数消费(执行)而不获取结果的

  public interface Consumer {

     Performs this operation on the given argument.

      @param t the input argument

    void accept(T t);
    }
 */
public class ConsumerDemo {
    @Test
    public void test01() {
        Consumer c = str -> System.out.println(str);
        c.accept("abcd");

    }

    @Test
    public void test02() {
        method("def",str-> System.out.println(str.length()));

    }

    public void method(String str, Consumer c) {
        c.accept(str);//String str="def"
                      //Consumer c = new ConsumerDemo$$Lambda$2();

    }
}
/*
   class ConsumerDemo$$Lambda$1 implements Consumer{

      public  void accept(String t){
            System.out.println(str);
      }
   }


   class ConsumerDemo$$Lambda$2 implements Consumer{

      public  void accept(String t){
            System.out.println(str.length());
      }
   }


 */
       /*
          Consumer接口中的默认方法
            //当我们需要对同一个内容执行一个连续的操作,可以使用andThen
            //同时也可以利用andThen来完成链式编程
            default Consumer andThen(Consumer after) {
               Objects.requireNonNull(after);
               return (T t) -> { accept(t); after.accept(t); };
            }
          需求:要求首先打印一个字符串的长度,接着再去将这个字符串全部转换成大写后再去打印

        */


import org.junit.Test;

import java.util.function.Consumer;

/*
   Consumer接口中的默认方法
     //当我们需要对同一个内容执行一个连续的操作,可以使用andThen
     //同时也可以利用andThen来完成链式编程
     default Consumer andThen(Consumer after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
     }
   需求:要求首先打印一个字符串的长度,接着再去将这个字符串全部转换成大写后再去打印

 */
public class ConsumerDemo02 {
    @Test
    public void test01() {
        method("abcd",
                str-> System.out.println(str.length()),
                        str-> System.out.println(str.toUpperCase()));
    }

    public void method(String str, Consumer c1, Consumer c2) {
        /*c1.accept(str);
        c2.accept(str);*/
        c1.andThen(c2).accept(str);//链式编程

    }
}

/*
  1. c1.andThen(c2)

   default Consumer andThen(Consumer after) {
        Objects.requireNonNull(after);//如果after为null,则抛控制异常
        //return (T t) -> { this.accept(t); after.accept(t); };
        //return (String t)->{c1.accept(t);c2.accept(t)}
        //return new ConsumerDemo02$$Lambda$1();  //返回一个Lambda表达式相当于返回该Lambda表达式对用的实现类对象
     }

   2.new ConsumerDemo02$$Lambda$1().accept("abcd")



     class ConsumerDemo02$$Lambda$1 implements Consumer {
        public void accept(String t){  //String t = "abcd"
        c1.accept(t);  //c1.accept("abcd");
        c2.accept(t);  //c2.accept("abcd");
        }


     }




 */
   c.Function
       /*
          Function接口
             适用于既传递参数,又获取执行结果的操作
             @FunctionalInterface
         public interface Function {
           R apply(T t);
           }

        */

public class Product {
    //商品名称
    private String productName;
    //商品价格
    private double productPrice;

    public Product(String productName, double productPrice) {
        this.productName = productName;
        this.productPrice = productPrice;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public double getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(double productPrice) {
        this.productPrice = productPrice;
    }

    @Override
    public String toString() {
        return "Peoduct{" +
                "productName='" + productName + '\'' +
                ", productPrice=" + productPrice +
                '}';
    }
}

import org.junit.Test;

import java.util.Arrays;
import java.util.function.Function;

/*
   Function接口
      适用于既传递参数,又获取执行结果的操作
      @FunctionalInterface
  public interface Function {
    R apply(T t);
    }

 */
public class FunctionDemo {
    @Test
    public void test01() {
        //1.将一个整数字符串,转换成一个整数返回
        Function f1=str->Integer.parseInt(str);
        Integer i = f1.apply("123");
        System.out.println(i + 3);
    }
    @Test
    public void test02() {
        //2.获取一个整型数组中最大的元素
        //Arrays方法   static void sort(int[] a, int fromIndex, int toIndex)
        //                   对指定 int 型数组按照数字从小到大排序
        Function f1 = arr -> {
            Arrays.sort(arr);
            return arr[arr.length - 1];//最大索引位置的元素就是最大元素
        };
        Integer max = f1.apply(new int[]{13, 23, 19, 1, 21});
        System.out.println(max);
    }

}
       /*
          Function接口的默认方法
                 // f1.apply(f2.apply(13))
               default  Function compose(Function                 before) {
               Objects.requireNonNull(before);
               return (V v) -> apply(before.apply(v));  //f1.apply(f2.apply(13))
              }

              //为了完成链式编程,会将第一个Function接口对应的Lambda的执行结果传递给第二个                Lambda表达式的参数,以此类推
               default  Function andThen(Function                 after) {
               Objects.requireNonNull(after);
               return (T t) -> after.apply(this.apply(t)); //相当于                 f2.apply(f1.apply(t))
             }
          需求:将一个字符串的首字符转换成大写,返回
                首先截取出字符串的首字母
                再将这个首字母转换成大写
        */


import org.junit.Test;

import java.util.function.Function;

/*
   Function接口的默认方法
          // f1.apply(f2.apply(13))
        default  Function compose(Function before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));  //f1.apply(f2.apply(13))
       }

       //为了完成链式编程,会将第一个Function接口对应的Lambda的执行结果传递给第二个Lambda表达式的参数,以此类推
        default  Function andThen(Function after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(this.apply(t)); //相当于 f2.apply(f1.apply(t))
      }
    需求:将一个字符串的首字符转换成大写,返回
         首先截取出字符串的首字母
         再将这个首字母转换成大写
 */
public class FunctionDemo02 {
    @Test
    public void test01() {
        String s = method("wang",
                str -> str.substring(0, 1),
                str -> str.toUpperCase());
        System.out.println(s);
    }

    public String method(String str, Function f1, Function f2) {
        /*String s1 = f1.apply(str);
        //System.out.println(s1);

        String s2 = f2.apply(s1);
        //System.out.println(s2);

        return s2;*/
        return f1.andThen(f2).apply(str);
    }

    @Test
    public void test02() {
        Function f1 = i -> i + 2;
        Function f2 = j -> j * 3;
        System.out.println(f1.andThen(f2).apply(13));//f2.apply(f1.apply(13))
        System.out.println(f1.compose(f2).apply(13));//f1.apply(f2.apply(13))
    }
}
   d.Predicate
       /*
          Predicate接口中的默认方法
               //相当于多个条件进行&&链接
               //可以进行链式编程
               //p1.and(p2).test(product)
              default Predicate and(Predicate other) {
               Objects.requireNonNull(other);
               return (t) -> test(t) && other.test(t);  //p1.test(t) && p2.test(t)
           }

              default Predicate negate() {
               return (t) -> !test(t);
           }
             default Predicate or(Predicate other) {
               Objects.requireNonNull(other);
               return (t) -> test(t) || other.test(t);
           }


import org.junit.Test;

import java.util.function.Predicate;

/*
  Predicate接口
      @FunctionalInterface
public interface Predicate {

    boolean test(T t);
 */
public class PredicateDemo {
    @Test
    public void test01() {
        Predicate p = str -> str.length() > 5;
        System.out.println(p.test("abc"));     //false
        System.out.println(p.test("abcdef"));  //true
    }
}
          需求:
              1.新建一个Product类,其中包含商品名称和商品的价格
              2.新建一个List集合,存储四个商品
               完成一下需求:
                 a.打印集合中价格<3000的商品信息
                 b.打印集合中商品名称包含联想,并且价格>=3000的商品的信息
                     商品名称要包含联想
                     商品价格>=3000
                 c.打印集合中商品名称包含华硕或者价格>7000的商品的信息
                 d.打印集合中商品名称不包含联想的商品信息
        */

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/*
   Predicate接口中的默认方法
        //相当于多个条件进行&&链接
        //可以进行链式编程
        //p1.and(p2).test(product)
       default Predicate and(Predicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);  //p1.test(t) && p2.test(t)
    }

       default Predicate negate() {
        return (t) -> !test(t);
    }
      default Predicate or(Predicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    需求:
       1.新建一个Product类,其中包含商品名称和商品的价格
       2.新建一个List集合,存储四个商品
        完成一下需求:
          a.打印集合中价格<3000的商品信息
          b.打印集合中商品名称包含联想,并且价格>=3000的商品的信息
              商品名称要包含联想
              商品价格>=3000
          c.打印集合中商品名称包含华硕或者价格>7000的商品的信息
          d.打印集合中商品名称不包含联想的商品信息
 */
public class PredicateDemo02 {
    @Test
    public void test01() {
        List products = Arrays.asList(
                new Product("联想笔记本", 3000),
                new Product("联想手机", 2000),
                new Product("华硕笔记本", 7000),
                new Product("三星冰箱", 10000)
        );
        method01(products,product -> product.getProductPrice()<3000);

    }
// a.打印集合中价格<3000的商品信息
    public void method01(List products, Predicate p) {
        //1.遍历products集合
        for (Product product : products) {
            if (p.test(product)) {//对当前遍历到的product对象执行对应的Lanbda表达式{}中的内容
                System.out.println(product);
            }
        }
    }

    @Test
    public void tast02() {
        List products = Arrays.asList(
                new Product("联想笔记本", 3000),
                new Product("联想手机", 2000),
                new Product("华硕笔记本", 7000),
                new Product("三星冰箱", 10000)
        );
        method02(products,
                product -> product.getProductName().contains("联想"),
                product -> product.getProductPrice()>=3000);
    }
    //b.打印集合中商品名称包含联想,并且价格>=3000的商品的信息
    public void method02(List products, Predicate p1, Predicate p2) {
        //1.遍历products集合
        for (Product product : products) {
            /*if (p1.test(product) && p2.test(product)) {
                System.out.println(product);
            }*/
            if (p1.and(p2).test(product)) {
                System.out.println(product);
            }
        }
    }
    @Test
    public void tast03() {
        List products = Arrays.asList(
                new Product("联想笔记本", 3000),
                new Product("联想手机", 2000),
                new Product("华硕笔记本", 7000),
                new Product("三星冰箱", 10000)
        );
        method03(products,
                product ->product.getProductName().contains("华硕") ,
                product -> product.getProductPrice()>7000);
    }
//c.打印集合中商品名称包含华硕或者价格>7000的商品的信息
    public void method03(List products, Predicate p1, Predicate p2) {
        //1.遍历products集合
        for (Product product : products) {
            if (p1.or(p2).test(product)) {   //product.getProductName().contains("华硕")||product.getProductPrice()>7000)
                System.out.println(product);
            }
        }
    }

    @Test
    public void tast04() {
        List products = Arrays.asList(
                new Product("联想笔记本", 3000),
                new Product("联想手机", 2000),
                new Product("华硕笔记本", 7000),
                new Product("三星冰箱", 10000)
        );
        method04(products, product ->
                product.getProductName().contains("联想"));
    }
    //d.打印集合中商品名称不包含联想的商品信息
    public void method04(List products, Predicate p1) {
        //1.遍历products集合.
        for (Product product : products) {
            if (p1.negate().test(product)) {   // ! product.getProductName().contains("联想")
                System.out.println(product);
            }
        }
    }
}

你可能感兴趣的:(python,java,前端)