1、函数式接口-概念及格式
函数式接口:有且只有一个抽象方法的接口(可以有其他的方法:默认方法,静态方法,私有方法…)
2、函数式接口-@FunctionalInterface注解
1)、在定义函数式接口时,为防止发生定义错误,可使用@FunctionalInterface注解,强制按照函数式接口的语法进行检查,如果语法错误,编译器会编译错误。
@FunctionalInterface
interface IA{//如果此接口不定义任何抽象方法,将会报错
public void show();
public void show1();//如果此接口定义多个抽象方法,也会报错
}
3、函数式接口-练习-自定义函数式接口(无参无返回值)
//无参,无返回值的函数式接口
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda表达式,代替"匿名内部类"
fun(() -> System.out.println("呵呵...."));
}
public static void fun(IA a){
a.show();
}
}
4、函数式接口-练习-自定义函数式接口(有参有返回值)
@FunctionalInterface
interface IA{
public int calc(int a, int b);
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda
fun((int m, int n) -> {
return m + n;
}, 10, 20);
}
public static void fun(IA a, int x, int y) {
int result = a.calc(x, y);
System.out.println("结果是:" + result);
}
}
5、函数式编程-Lambda的应用-延迟执行
@FunctionalInterface
interface IA{
public String buildString();
}
public class Demo {
public static void main(String[] args) {
String s1 = "日志级别:1";
String s2 = "异常信息:NullPointerException";
String s3 = "日期:2018-09-22";
//1.使用匿名内部类的方式
fun(1, new IA(){
@Override
public String buildString() {
System.out.println("执行了....");
return s1 + s2 + s3;
}
});
//2.使用Lambda代替匿名内部类
fun(1,()->{
System.out.println("执行啦.....");
return s1 + s2 + s3;});
}
//一个打印日志
// public static void fun(int level, String msg) {//原方法
public static void fun(int level, IA a) {//改为接口类型形参
if (level == 1) {//只有级别为1时,才打印日志--延迟
System.out.println(a.buildString());
}
}
}
6、函数式编程-Lambda的应用-自定义接口-Lambda作为参数和返回值
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
//Lambda作为形参
f1(() -> System.out.println("呵呵呵"));
//Lambda作为返回值
IA a = f2();
a.show();
}
//作为"形参"
public static void f1(IA ia) {
ia.show();
}
//作为"返回值"
public static IA f2(){
return () -> System.out.println("嘻嘻...");
}
}
函数式接口作为形参时,必须要使用这个接口的实现子类来作为实参,而这个实现子类又必须要重写接口的抽象方法,所以就可以直接使用Lambda表达式作为实参传入(做返回值同样)
7、函数式编程-Lambda的应用-类库接口-Lambda作为形参和返回值
public class Demo {
public static void main(String[] args) {
//1.Lambda作为形参
f1(()-> System.out.println("线程启动!"));
//2.Lambda作为返回值
Runnable r = f2();
new Thread(r).start();
}
//使用Lambda作为"形参"
public static void f1(Runnable runnable) {
new Thread(runnable).start();
}
//使用Lambda作为"返回值"
public static Runnable f2(){
return () -> System.out.println("线程启动....");
}
}
8、方法引用-使用自定义静态方法替代Lambda(“引用”理解为“替代”)
方法引用:就是使用已存在的方法替代Lambda表达式
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
fun(Demo::method);//Demo::method代替:Lambda,Lambda代替:匿名内部类。
fun(Demo::f2);//OK的--静态方法,必须通过"类名"引用,不能通过"对象名"引用。
fun(Demo::f3);//错误的,因为其参数不同
}
public static void fun(IA ia) {
ia.show();
}
//其它方法
public static void method(){
System.out.println("呵呵...");
}
private static void f2(){
System.out.println("嘻嘻....");
}
public static void f3(String s) {
System.out.println(s);
}
}
9、方法引用-使用类库静态方法替代Lambda
@FunctionalInterface
interface IA{
//打印一个int数组的所有元素
public String printArray(int[] arr);
}
public class Demo {
public static void main(String[] args) {
int[] arr = {1432,432,432,4325,424,324,32,54,51,412,35,25,144,3};
//使用匿名内部类
fun(new IA(){
@Override
public String printArray(int[] arr) {
StringBuilder bld = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
bld.append(arr[i]);
if (i < arr.length - 1) {
bld.append(" ,");
}else{
bld.append("]");
}
}
return bld.toString();
}
},arr);
//使用Lambda
fun((int[] array) -> {
StringBuilder bld = new StringBuilder("[");
for (int i = 0; i < array.length; i++) {
bld.append(array[i]);
if (i < array.length - 1) {
bld.append(" ,");
} else {
bld.append("]");
}
}
return bld.toString();
}, arr);
//使用Arrays的toString()方法来替代:Lambda
fun(Arrays::toString, arr);
}
//定义方法,可以打印数组
public static void fun(IA a, int[] arr) {
System.out.println(a.printArray(arr));
}
}
10、方法引用-替代原则
“替代的方法”的形参、返回值类型,必须和被替换的“函数式接口”中的抽象方法一致
11、方法引用-使用对象成员方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Student{
public void playGame(Game game) {
System.out.println("我开始打游戏:");
game.run();
}
}
class Teacher{
public void like(){
System.out.println("我喜欢喝茶(我是老师).....");
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.playGame(()-> System.out.println("王者荣耀开始运行....."));
stu.playGame(()-> System.out.println("我喜欢喝茶...."));
//使用Teacher类的like()方法来代替Lambda表达式,打印:我喜欢喝茶....
Teacher t = new Teacher();
stu.playGame(t::like);//引用Teacher的like()方法。
//或者
stu.playGame(new Teacher()::like);
}
}
12、方法引用-使用super父类方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Fu{
public void like(){
System.out.println("我喜欢喝啤酒(我是父亲)....");
}
}
class Student extends Fu{
public void playGame(Game game) {
System.out.println("我开始打游戏:");
game.run();
}
public void show(){
//1.使用Lambda
playGame(() -> System.out.println("我喜欢喝啤酒...."));
//2.使用父类的like方法代替Lambda表达式
playGame(super::like);//使用父类的like方法代替Lambda表达式
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
13、方法引用-使用this本类方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Student{
public void playGame(Game game) {
System.out.println("我开始打游戏:");
game.run();
}
public void show(){
// playGame(() -> System.out.println("我喜欢打羽毛球...."));
playGame(this::ymq);
}
public void ymq(){
System.out.println("我喜欢打羽毛球....");
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
14、方法引用-类的构造器引用
1)、无参的构造方法
class Cat{
public Cat(){
}
public void eat(){
System.out.println("小猫吃鱼....");
}
}
interface CatFactory{
//生产Cat
public Cat getCat();
}
public class Demo {
public static void main(String[] args) {
//调用fun
//1.使用:匿名内部类
fun(new CatFactory() {
@Override
public Cat getCat() {
return new Cat();
}
});
//2.使用Lambda表达式
fun(()->{return new Cat();});
//3.使用Cat的无参构造方法替代:getCat()方法
fun(Cat::new);
}
public static void fun(CatFactory cf) {
Cat c = cf.getCat();
c.eat();
}
}
2)、有参构造方法
class Cat{
private String name;
public Cat(){
}
public Cat(String name) {
this.name = name;
}
public void eat(){
System.out.println("我是一只 " + name + " 我爱吃鱼....");
}
}
interface CatFactory{
//生产Cat
public Cat getCat(String name);
}
public class Demo {
public static void main(String[] args) {
//调用fun
//1.使用:匿名内部类
fun(new CatFactory() {
@Override
public Cat getCat(String name) {
return new Cat(name);
}
},"机器猫");
//2.使用Lambda表达式
fun((String n)->{return new Cat(n);},"机器猫");
//3.使用Cat的有参构造方法替代:getCat(String name)方法
fun(Cat::new,"机器猫");
}
public static void fun(CatFactory cf,String name) {
Cat c = cf.getCat(name);
c.eat();
}
}
15、方法引用-数组构造器引用
@FunctionalInterface
interface IA{
public int[] getArr(int len);
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda
fun((int len)->{return new int[len];},10);
//3.使用数组的构造器代替:Lambda
fun(int[]::new,15);
}
public static void fun(IA a,int len){
int[] arr = a.getArr(len);
System.out.println(arr.length);
}
}
16、常用函数式接口-生产者接口-Supplier接口
生产者接口:只生产数据,不接收参数
public class Demo {
public static void main(String[] args) {
show(()->{return 10;});
show2(()->{return "Hello";});
}
public static void show(Supplier<Integer> ia) {
Integer n = ia.get();
System.out.println(n);
}
public static void show2(Supplier<String> ia) {
String s = ia.get();
System.out.println(s);
}
}
17、常用函数式接口-消费者接口-Consumer接口-抽象方法accept
消费者接口:只接收参数,无返回值
public class Demo {
public static void main(String[] args) {
//1.匿名内部类
fun(new Consumer<String>() {
@Override
public void accept(String string) {
System.out.println(string.toLowerCase());
}
}, "Hello");
//2.使用Lambda
fun((String s) -> System.out.println(s.toUpperCase()),"Hello");
}
public static void fun(Consumer<String> consumer,String s) {
consumer.accept(s);
}
}
18、常用函数式接口-Consumer接口-默认方法andThen
将俩个Consumer对象的accept()方法的结果连在一起
public static void main(String[] args) {
fun((String s) -> System.out.println(s.toLowerCase()),
(String s) -> System.out.println(s.toUpperCase()), "Hello");
}
public static void fun(Consumer<String> one, Consumer<String> two,String s) {
one.andThen(two).accept(s);
}
复习
-
能够使用@FunctionalInterface注解
强制定义为函数式接口
-
能够自定义无参无返回函数式接口
@FunctionalInterface interface IA{ public void show(); }
-
能够自定义有参有返回函数式接口
@FunctionalInterface interface IA{ public Srting show(String str1,String str2); }
-
能够理解Lambda延迟执行的特点
interface IA{ public String buildString(); } public static void main(Stirng[] args){ String s1 = "..."; String s2 = "..."; String s3 = "..."; log(1,()->{return s1 + s2 + s3;}); } public static void log(int level,IA msg){ if(level == 1){//只有当level = 1时,才调方法。 System.out.println(msg.buildString()); } }
-
能够使用Lambda作为方法的参数
main(){ fun(()->System.out.println("线程开始运行")); } public static void fun(Runnable r){ }
-
能够使用Lambda作为方法的返回值
main(){ Runnable r = getRun(); new Thread(r).start(); } public static Runnable getRun(){ return ()->System.out.println("线程开始运行"); }
-
能够使用输出语句的方法引用
interface IA{ public void show(String s); } public static void main(String[] args){ //1.使用Lambda fun((String s)->System.out.println(s),"Hello"); //2.使用System.out.println(String s)方法代替 fun(System.out::println,"Hello"); } public sttaic void fun(IA a,String s){ a.show(s); }
-
能够通过4种方式使用方法引用
静态方法引用:
interface IA{ public void printArray(int[] arr); } main(){ int[] arr = {22,4,32,33,14,32,4,234,324,32}; fun(Arrays::toString,arr); } public static void fun(IA a,int[] arr){ a.printArray(arr); }
成员方法引用:
interface Game{ public void run(); } class Student{ public void playGame(Game g){ g.run(); } } class Teacher{ public void like(){ System.out.println("我喜欢喝茶..."); } } main(){ Student stu = new Student(); stu.playGame(()->System.out.println("我开始打游戏...")); //使用其它类的成员方法代替: Teacher t = new Teacher(); stu.playGame(t::like); }
super引用:
interface Game{ public void run(); } class Fu{ public void like(){ System.out.println("我喜欢喝啤酒..."); } } class Student extends Fu{ public void playGame(Game g){ g.run(); } public void show(){ playGame(()->System.out.println("我喜欢喝啤酒..."); playGame(super::like);//引用父类的like方法 } } main(){ Student stu = new Student(); stu.show(); }
this引用:
interface Game{ public void run(); } class Student{ public void playGame(Game g){ g.run(); } public void show(){ //使用Lambda // playGame(()->System.out.println("我喜欢泡妞..."); //使用字节的like()方法代替 playGame(this::like); } public void like(){ System.out.println("我喜欢泡妞..."); } } main(){ Student stu = new Student(); stu.show(); }
-
能够使用类和数组的构造器引用
无参的构造方法:
class Cat{ public Cat(){ } public void eat(){ System.out.println("小猫吃鱼...."); } } interface CatFactory{ //生产Cat public Cat getCat(); } public class Demo { public static void main(String[] args) { //调用fun //1.使用:匿名内部类 fun(new CatFactory() { @Override public Cat getCat() { return new Cat(); } }); //2.使用Lambda表达式 fun(()->{return new Cat();}); //3.使用Cat的无参构造方法替代:getCat()方法 fun(Cat::new); } public static void fun(CatFactory cf) { Cat c = cf.getCat(); c.eat(); } }
有参构造方法:
class Cat{ private String name; public Cat(){ } public Cat(String name) { this.name = name; } public void eat(){ System.out.println("我是一只 " + name + " 我爱吃鱼...."); } } interface CatFactory{ //生产Cat public Cat getCat(String name); } public class Demo { public static void main(String[] args) { //调用fun //1.使用:匿名内部类 fun(new CatFactory() { @Override public Cat getCat(String name) { return new Cat(name); } },"机器猫"); //2.使用Lambda表达式 fun((String n)->{return new Cat(n);},"机器猫"); //3.使用Cat的有参构造方法替代:getCat(String name)方法 fun(Cat::new,"机器猫"); } public static void fun(CatFactory cf,String name) { Cat c = cf.getCat(name); c.eat(); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } 数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } } //数组构造器: @FunctionalInterface interface IA{ public int[] getArr(int len); } public class Demo { public static void main(String[] args) { //2.使用Lambda fun((int len)->{return new int[len];},10); //3.使用数组的构造器代替:Lambda fun(int[]::new,15); } public static void fun(IA a,int len){ int[] arr = a.getArr(len); System.out.println(arr.length); } }
-
能够使用Supplier函数式接口
生产者:
@FunctionalInterface public interface Supplier<T> { T get(); }
使用:
public static void main(String[] args) { show(()->{return 10;}); show2(()->{return "Hello";}); } public static void show(Supplier<Integer> ia) { Integer n = ia.get(); System.out.println(n); } public static void show2(Supplier<String> ia) { String s = ia.get(); System.out.println(s); }
-
能够使用Consumer函数式接口
消费者接口:
@FunctionalInterface public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
使用:
public static void main(String[] args) { //2.使用Lambda fun((String s) -> System.out.println(s.toUpperCase()),"Hello"); } public static void fun(Consumer<String> consumer,String s) { consumer.accept(s); }