1、什么是函数式接口?
简单来说一个接口里面有且只有一个抽象方法,那么这个接口我们就称它为函数式接口。
Tips:
我们知道在jdk1.8之前,接口里的方法都要求是抽象方法,接口中的变量则一定是全局静态变量,但是到了jdk1.8 接口里的内容则有大不同!在jdk1.8之后,接口里除了抽象方法之外,也可以有非抽象方法,但是这个非抽象方法只包含两类,第一种则是静态方法,另外一种则必须用default关键字加以定义。
因此,更加具体来说,只要这个接口里只有一个抽象方法,可以有若干个非抽象方法,我们也称这个接口为函数式接口。
举个例子:
(1)People接口:
package com.day20221008;
public interface People {
//默认是public final static类型的变量
int a = 10;
//默认是抽象方法
void dance();
default void sing(){
System.out.println("我爱唱歌");
}
static void drawing(){
System.out.println("我爱跳舞");
}
}
(2)FunctionDemo接口:
package com.day20221008;
public class FunctionDemo{
public static void main(String[] args) {
//函数式接口声明
People people1 = new People() {
@Override
public void dance() {
System.out.println("我喜欢跳锁舞");
}
};
people1.dance();
//函数式接口声明+Lambda表达式
People people = () ->{
System.out.println("我喜欢跳爵士");
};
people.dance();
}
}
(3)运行结果
补充:
在这里除了lambda表达式之外,对于第一种实现方法大家是不是感觉有点似曾相识,没错,他就是匿名内部类,大家还记得匿名内部类吗?
匿名内部类:匿名内部类是局部内部类的一种简化形式.本质上是一个对象,是实现了该接口或继承了该抽象类的子类对象.。
因此,其实总结来说函数式接口相当于匿名内部类的一种特殊情况,因为函数式接口要求接口中有且只有一个抽象方法才可以,并且lambda表达式也只是适于函数式接口,因为如果匿名内部类声明的接口若只有一个抽象方法时,那么他也就等价于函数式接口了!
(1)Animals接口:
package com.day20221008;
public interface Animals {
void eat();
void drink();
}
(2)实现类:
package com.day20221008;
public class FunctionDemo{
public static void main(String[] args) {
//匿名内部类
Animals tiger = new Animals() {
@Override
public void eat() {
System.out.println("我是老虎,我要吃肉");
}
@Override
public void drink() {
System.out.println("我是老虎,我要喝水");
}
};
Animals rabbit = new Animals() {
@Override
public void eat() {
System.out.println("我是兔子,我要吃草");
}
@Override
public void drink() {
System.out.println("我是兔子,我要喝水");
}
};
tiger.eat();
tiger.drink();
rabbit.eat();
rabbit.drink();
}
}
2、Lambda表达式:
(1)什么是Lambda表达式?
Lambda表达式是JAVA8中提供的一种新的特性,是一个匿名函数方法。注意咱这里它只适用于函数式接口,而不是说适合所有类型的匿名内部类。
(2)语法格式:
Lambda表达式就是对函数式接口中抽象方法的实现,是对其匿名内部类的一个简写,只保留了方法的参数列表和方法体,其他的成分可以省略。因此,Lambda表达式的格式非常简洁,只有三部分组成:
参数列表
箭头
方法体
总结:(参数列表)->{方法体}
注意注意:
小括号内参数的参数类型可以省略。
小括号有且只有一个参数,则小括号可以直接省略。
如果大括号有且只有一个语句,无论是否有返回值,大括号、return关键字、分号可以省略。
注意 -> 中间不可以其他字符,负责会报错。
具体的使用方法大家可以在下面的四个例子中好好感受一下!
3、四大函数式接口:
结合jdk的开发手册,函数式接口里面主要非为四类,其他的都是综合。
(1)Consumer消费型接口:只有输入,没有输出。
package com.day20221008;
import java.sql.SQLOutput;
import java.util.function.Consumer;
public class FourFunctionDemo {
public static void main(String[] args) {
//消费型接口
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("我是消费型接口"+s);
}
};
consumer.accept(" ,我是传递的参数");
//Lambda表达式版
Consumer<String> consumer1 = (a) -> {
System.out.println("我是消费型接口的lambda版本"+a);
};
consumer1.accept(",我是传递的参数");
}
}
(2)Supplier供给型接口:只有输出,没有输入。
package com.day20221008;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return "我是供给型接口";
}
};
System.out.println(supplier.get());
Supplier<String> supplier1 = () ->{
return "我是Lambda版供给型接口";
};
System.out.println(supplier1.get());
}
}
(3)Predicate断定型接口:有一个输入参数,但是输出值为boolean值。
package com.day20221008;
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String s) {
System.out.println("我是断定型的接口"+s);
return false;
}
};
System.out.println(predicate.test(",我是参数"));
//Lambda表达式类型
Predicate<String> predicate1 = (s) ->{
System.out.println("我是Lambda类型的断定型的接口"+s);
return true;
};
System.out.println(predicate1.test(",我是参数"));
}
}
(4)Function函数型接口:有一个输入,也有一个输出。
package com.day20221008;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.function.Function;
public class FunctionDemo1 {
public static void main(String[] args) {
Function<String, Integer> function = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
System.out.println("我是函数型接口" + s);
return 4;
}
};
System.out.println(function.apply(",我是参数"));
//lambda表达式版本
Function<String, Integer> function1 = (a) ->{
System.out.println("我是lambda函数型接口"+a);
return 5;
};
System.out.println(function1.apply(",我是参数"));
}
}
补充一下,在这里我真的是鼓励大家去敲一遍代码,大家可能会认为自己理解了一个,能够举一反三,其实大家都明白,但是缺少实践,切不可眼高手低!
**
4、Stream流
**
(1) 什么是流?
数据的渠道,用于操作数据源所生成的元素序列。
个人理解,就相当于把集合或者数组中一个一个数据排放在一个管道里面,所形成的的一个管道元素序列。
(2)流是用来干什么的?
根据流的定义,我们可以看出操作二字,因此流的出现主要是对数据源中的数据进行各种操作的。
集合讲究的是数据,流讲究的是计算。
(3)流的特点?
Stream 自己不会存储元素。
Stream 不会改变源对象,相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
其中包含很多方法,在这里先留一个坑,然后以后有机会在专门写一篇关于Stream流的博客。给大家推荐两篇Stream流的文章:
(1)https://blog.csdn.net/qq_37992410/article/details/120842966
(2)https://blog.csdn.net/weixin_45082647/article/details/107001387
我个人感觉这两篇博客写的特别全面,大家可以照着这两篇博客敲一遍,相信你一定会大有收获!!!