知识模块:
一.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 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 andThen(Consumer super T> 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 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 {
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 super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v)); //f1.apply(f2.apply(13))
}
//为了完成链式编程,会将第一个Function接口对应的Lambda的执行结果传递给第二个 Lambda表达式的参数,以此类推
default Function 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 Function 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 Function 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 {
@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 super T> 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 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 {
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 super T> 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 super T> 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);
}
}
}
}