知识模块:
一.Lambda表达式概述:
二.Lambda表达式使用前提
三.Lambda表达式一.完整格式二.简略格式
四.Lanbda表达式原理
五.Java中已有的函数式接口a.Supplierb.Consumer接口c.Functiond.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 {@Testpublic void test01() {method("你好Lambda表达式",(String str)->{System.out.println(str);});}public void method(String str, Printer p) {p.print(str);}@Testpublic 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 {@Testpublic void test01() {method("你好", (str) -> {System.out.println(str);});method02(4, 19, (a, b) -> {return a + b;});}@Testpublic void test02() {method("大家好", str -> {System.out.println(str);});}@Testpublic 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 {@Testpublic void test01() {method("你好Lambda表达式", (String str) -> {System.out.println(str);});}public void method(String str, Printer p) {p.print(str);}@Testpublic void test02() {Printer p = str -> System.out.println(str);System.out.println(p);for (Class<?> in : p.getClass().getInterfaces()) {System.out.println(in);}}@Testpublic void test03() {Printer p = str -> System.out.println(str); //相当于 Painter p = new LambdaDemo02$$Lambda$1();//多态p.print("abc");}}/*
//在程序的运行时期,会生成这个Lambda表达式对应的接口的一个实现类,并且重写接口中的抽象方法,重写的目标对应Lambda表达式{}中的内容而且这个可u是一个内部类
public class LambdaDemo05 {@Testpublic 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 {@Testpublic 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);}@Testpublic 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);}@Testpublic 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 {@Testpublic 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=12return a+b;}}
}*/
五.Java中已有的函数式接口a.Supplier/*Supplier接口:适用于只获取结果不传递参数的操作@FunctionalInterfacepublic interface Supplier<T> {Gets a result.@return a resultT 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<T> {Gets a result.@return a resultT get();}Arrays类中的toString方法static String toString(int[] a)将数组中的元素拼接成一个字符串,然后返回这个字符串*/
public class SupplierDemo {@Testpublic void test01() {//获取1~10之间的随机数int i = new Random().nextInt(10) + 1;//[1,11)System.out.println(i);}@Testpublic void test02() {//Supplier<Integer>s=()->{return new Random().nextInt(10) + 1;};Supplier<Integer>s=()-> new Random().nextInt(10) + 1;System.out.println(s.get());}@Testpublic void test03() {//获取10个1~10之间的随机数,将这些随机数存放到一个数组,最后打印数组中的元素int[] arr = new int[10];Supplier<Integer> s = () -> new Random().nextInt(10) + 1;for (int i = 0; i < 10; i++) {arr[i]=s.get();}Supplier<String> s2 = () -> Arrays.toString(arr);System.out.println(s2.get());}
}
/*class SupplierDemo$$Lambda$1 implements Supplier<Integer>{public Integer get(){return new Random().nextInt(10)+1;}}*/
b.Consumer接口/*Consumer接口一般用于值传递参数消费(执行)而不获取结果的public interface Consumer<T> {Performs this operation on the given argument.@param t the input argumentvoid accept(T t);}*/
import org.junit.Test;import java.util.concurrent.Flow;
import java.util.function.Consumer;/*Consumer接口一般用于值传递参数消费(执行)而不获取结果的public interface Consumer<T> {Performs this operation on the given argument.@param t the input argumentvoid accept(T t);}*/
public class ConsumerDemo {@Testpublic void test01() {Consumer<String> c = str -> System.out.println(str);c.accept("abcd");}@Testpublic void test02() {method("def",str-> System.out.println(str.length()));}public void method(String str, Consumer<String> c) {c.accept(str);//String str="def"//Consumer<String> c = new ConsumerDemo$$Lambda$2();}
}
/*class ConsumerDemo$$Lambda$1 implements Consumer<String>{public void accept(String t){System.out.println(str);}}class ConsumerDemo$$Lambda$2 implements Consumer<String>{public void accept(String t){System.out.println(str.length());}}*/
/*Consumer接口中的默认方法//当我们需要对同一个内容执行一个连续的操作,可以使用andThen//同时也可以利用andThen来完成链式编程default Consumer<T> andThen(Consumer<? super T> 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<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}需求:要求首先打印一个字符串的长度,接着再去将这个字符串全部转换成大写后再去打印*/
public class ConsumerDemo02 {@Testpublic void test01() {method("abcd",str-> System.out.println(str.length()),str-> System.out.println(str.toUpperCase()));}public void method(String str, Consumer<String> c1, Consumer<String> c2) {/*c1.accept(str);c2.accept(str);*/c1.andThen(c2).accept(str);//链式编程}
}/*1. c1.andThen(c2)default Consumer<T> andThen(Consumer<? super T> 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<String> {public void accept(String t){ //String t = "abcd"c1.accept(t); //c1.accept("abcd");c2.accept(t); //c2.accept("abcd");}}*/
c.Function/*Function接口适用于既传递参数,又获取执行结果的操作@FunctionalInterfacepublic interface Function<T, R> {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;}@Overridepublic String toString() {return "Peoduct{" +"productName='" + productName + '\'' +", productPrice=" + productPrice +'}';}
}
import org.junit.Test;import java.util.Arrays;
import java.util.function.Function;/*Function接口适用于既传递参数,又获取执行结果的操作@FunctionalInterfacepublic interface Function<T, R> {R apply(T t);}*/
public class FunctionDemo {@Testpublic void test01() {//1.将一个整数字符串,转换成一个整数返回Function<String,Integer> f1=str->Integer.parseInt(str);Integer i = f1.apply("123");System.out.println(i + 3);}@Testpublic void test02() {//2.获取一个整型数组中最大的元素//Arrays方法 static void sort(int[] a, int fromIndex, int toIndex)// 对指定 int 型数组按照数字从小到大排序Function<int[], Integer> 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 <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v)); //f1.apply(f2.apply(13))}//为了完成链式编程,会将第一个Function接口对应的Lambda的执行结果传递给第二个 Lambda表达式的参数,以此类推default <V> Function<T, V> andThen(Function<? super R, ? extends V> 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 <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v)); //f1.apply(f2.apply(13))}//为了完成链式编程,会将第一个Function接口对应的Lambda的执行结果传递给第二个Lambda表达式的参数,以此类推default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(this.apply(t)); //相当于 f2.apply(f1.apply(t))}需求:将一个字符串的首字符转换成大写,返回首先截取出字符串的首字母再将这个首字母转换成大写*/
public class FunctionDemo02 {@Testpublic void test01() {String s = method("wang",str -> str.substring(0, 1),str -> str.toUpperCase());System.out.println(s);}public String method(String str, Function<String, String> f1, Function<String, String> 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);}@Testpublic void test02() {Function<Integer, Integer> f1 = i -> i + 2;Function<Integer, Integer> 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<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t); //p1.test(t) && p2.test(t)}default Predicate<T> negate() {return (t) -> !test(t);}default Predicate<T> or(Predicate<? super T> 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<T> {boolean test(T t);*/
public class PredicateDemo {@Testpublic void test01() {Predicate<String> p = str -> str.length() > 5;System.out.println(p.test("abc")); //falseSystem.out.println(p.test("abcdef")); //true}
}
需求:1.新建一个Product类,其中包含商品名称和商品的价格2.新建一个List集合,存储四个商品完成一下需求:a.打印集合中价格<3000的商品信息b.打印集合中商品名称包含联想,并且价格>=3000的商品的信息商品名称要包含联想商品价格>=3000c.打印集合中商品名称包含华硕或者价格>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<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t); //p1.test(t) && p2.test(t)}default Predicate<T> negate() {return (t) -> !test(t);}default Predicate<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t);}需求:1.新建一个Product类,其中包含商品名称和商品的价格2.新建一个List集合,存储四个商品完成一下需求:a.打印集合中价格<3000的商品信息b.打印集合中商品名称包含联想,并且价格>=3000的商品的信息商品名称要包含联想商品价格>=3000c.打印集合中商品名称包含华硕或者价格>7000的商品的信息d.打印集合中商品名称不包含联想的商品信息*/
public class PredicateDemo02 {@Testpublic void test01() {List<Product> 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<Product> products, Predicate<Product> p) {//1.遍历products集合for (Product product : products) {if (p.test(product)) {//对当前遍历到的product对象执行对应的Lanbda表达式{}中的内容System.out.println(product);}}}@Testpublic void tast02() {List<Product> 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<Product> products, Predicate<Product> p1, Predicate<Product> 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);}}}@Testpublic void tast03() {List<Product> 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<Product> products, Predicate<Product> p1, Predicate<Product> p2) {//1.遍历products集合for (Product product : products) {if (p1.or(p2).test(product)) { //product.getProductName().contains("华硕")||product.getProductPrice()>7000)System.out.println(product);}}}@Testpublic void tast04() {List<Product> 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<Product> products, Predicate<Product> p1) {//1.遍历products集合.for (Product product : products) {if (p1.negate().test(product)) { // ! product.getProductName().contains("联想")System.out.println(product);}}}
}