函数式接口
函数式接口:有且仅有一个抽象方法的接口
Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是用于Lambda使用的接口
只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利推导
如何检验接口是否是函数式接口:
- @FunctionalIneterface
- 放于接口的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
下面给出示例代码:
代码语言:javascript复制public class MyInterfaceDemo {
public static void main(String[] args) {
//我们采用lambda方法来创建接口对象
MyInterface my = () -> {
System.out.println("函数式接口");
};
//直接调用方法,方法是由lambda标注的
my.show();
}
}
代码语言:javascript复制//函数式接口标记
@FunctionalInterface
public interface MyInterface {
void show();
}
函数式接口作为方法的参数
需求:
- 定义一个类(RunnableDemo),在类中提供两个方法
- startThread(Runnable r):方法参数是Runnable函数式接口
- main():调用startThread方法
下面给出代码示例:
代码语言:javascript复制public class RunnableDemo {
public static void main(String[] args) {
//第一种方法:匿名函数类
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() ":" "启动了");
}
});
//第二种方法,lambda
startThread(() -> { System.out.println(Thread.currentThread().getName() ":" "启动了");});
}
//定义方法
public static void startThread(Runnable r)
{
new Thread(r).start();
}
}
函数式接口作为方法的返回值
需求:
- 定义一个类(ComparatorDemo),在类中提供两个方法
- Comparator getComparator():方法返回值是一个Comparator,用作比较方法
- main():调用 getComparator方法
下面给出代码示例:
代码语言:javascript复制import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
public class ComparatorDemo {
public static void main(String[] args) {
//构造使用场景
ArrayList<String> arrayList = new ArrayList<>();
//先添加一些元素
arrayList.add("aa");
arrayList.add("ccc");
arrayList.add("bbbb");
arrayList.add("d");
//我们输出查看结果:
System.out.println(arrayList);
//首先我们使用默认排序方法
Collections.sort(arrayList);
//我们输出查看结果:
System.out.println(arrayList);
//我们使用带Comparator的排序方法
//这里我们通过GetComparator获得Comparator
Collections.sort(arrayList,getComparator2());
//我们输出查看结果:
System.out.println(arrayList);
}
public static Comparator<String> getComparator1() {
//这里我们通过构造器方法创建
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
}
public static Comparator<String> getComparator2() {
//这里我们通过lambda方法来创建
return (s1, s2) -> s1.length() - s2.length();
}
}
函数式常用接口
下面我们介绍四种函数式常用接口:
- Supplier接口:用于获得数据结果
- Consumer接口:用于消费所加载的数据
- Predicate接口:用于判断所加载的数据
- Function接口:用于进行数据类型转换
Supplier接口
Supplier:包含一个无参的方法
- T get():获得结果
- 该方法不需要参数,会按照实现逻辑(Lambda表达式实现)返回一个数据
- Supplier接口被称为生产型接口,如果我们指定了接口的泛型是什么类型,get方法就会产生什么类型
下面给出示例代码:
代码语言:javascript复制import java.util.function.Supplier;
public class Demo {
public static void main(String[] args) {
//我们输出由方法获得的值
//这里是使用lambda作为参数
System.out.println(getString(() -> "胡桃"));
System.out.println(getInteger(() -> 30));
}
//GetString
public static String getString(Supplier<String> sup){
return sup.get();
}
//GetInteger
public static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
练习:
- 定义一个类(SupplierTest),在类中提供两个方法
- int getMax():返回数组中最大的值
- main():调用 getMax方法
下面给出示例代码:
代码语言:javascript复制import java.util.function.Supplier;
public class Demo1 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {2,13,44,76,52};
//获得最大值
int max = getMax(() -> {
int maxValue = arr[0];
for(int i=0;i< arr.length;i ){
if(arr[i] > maxValue){
maxValue = arr[i];
}
}
return maxValue;
});
System.out.println(max);
}
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
}
Consumer接口
Consumer:包含两个方法
- void accept(T t):对给定的参数执行此操作
- default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
- Consumer接口也被称为消费型接口,它消费的数据类型由泛型指定
下面给出示例代码:
代码语言:javascript复制import java.util.function.Consumer;
public class Demo1 {
public static void main(String[] args) {
//Consumer消费一个字符串
operatorString1("胡桃",(String name) -> {
System.out.println(name);
});
//Consumer不同方法消费同一个字符串
operatorString2("胡桃",(String name)-> System.out.println(name),(String name) -> System.out.println(new StringBuilder(name).reverse().toString()));
}
//Consumer消费一个字符串
public static void operatorString1(String name, Consumer<String> con){
con.accept(name);
}
//Consumer不同方法消费同一个字符串
public static void operatorString2(String name, Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(name);
}
}
练习:
- 创造一个String数组,数组以“姓名,年龄”来组成
- 我们用Consumer接口来分别获取姓名和年龄,并输出
下面给出示例代码:
代码语言:javascript复制import java.util.function.Consumer;
public class Demo2 {
public static void main(String[] args) {
//创建一个数组
String[] strArray = {"胡桃,18","钟离,20","七七,12"};
//针对str做出输出
printInfo(strArray,(String str) -> System.out.print(str.split(",")[0])
,(String str) -> System.out.println(Integer.parseInt(str.split(",")[1])));
}
//创造消费方法
private static void printInfo(String[] strArray, Consumer<String> con1,Consumer<String> con2){
for(String str : strArray){
con1.andThen(con2).accept(str);
}
}
}
Predicate接口
Predicate:常用四个方法
- boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
- dafault predicate negate():返回一个逻辑的否定,对应逻辑非
- dafault predicate and():返回一个组合判断,对应短路与
- dafault predicate or()返回一个组合判断,对应短路或
- Predicate接口常用于判断参数是否满足指定条件
下面给出示例代码:
代码语言:javascript复制import java.util.function.Predicate;
public class Demo1 {
public static void main(String[] args) {
System.out.println(test("Jerry",(String s) -> s.length()>8));
System.out.println(negateTest("Jerry",(String s) -> s.length()>8));
System.out.println(andTest("Jerry",(String s) -> s.length()<8,(String s) -> s.length()>3));
System.out.println(orTest("Jerry",(String s) -> s.length()>10,(String s) -> s.length()<3));
}
public static boolean test(String s, Predicate<String> pre){
//对s进行测试,测试内容在main中用lambda完成
return pre.test(s);
}
public static boolean negateTest(String s,Predicate<String> pre){
//对s进行反向测试,得到的结果是相反结果
return pre.negate().test(s);
}
public static boolean andTest(String s,Predicate<String> pre1,Predicate<String> pre2){
//对s进行测试,测试是否同时满足两个条件
return pre1.and(pre2).test(s);
}
public static boolean orTest(String s,Predicate<String> pre1,Predicate<String> pre2){
//对s进行测试,测试是否满足至少一个条件
return pre1.and(pre2).test(s);
}
}
练习:
- 我们给出String[] stArray
- 通过Predicate接口获取满足条件的String并输出
下面给出示例代码:
代码语言:javascript复制import java.util.function.Predicate;
public class Demo2 {
public static void main(String[] args) {
//创造字符串对象
String[] arr = {"芽衣,29","雷神,33","提亚娜,29"};
//调用方法
printInfo(arr,(String s) -> s.split(",")[0].length()>2,(String s) -> Integer.parseInt( s.split(",")[1])<30);
}
private static void printInfo(String[] strArray, Predicate<String> pre1,Predicate<String> pre2){
for(String str : strArray){
boolean b = pre1.and(pre2).test(str);
if(b){
System.out.println(str);
}
}
}
}
Funciton接口
Function<T,R>:常用的两个方法
- R apply(T t):将此函数应用于给定的参数
- dafault Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
- Function<T,R>接口常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
下面给出示例代码:
代码语言:javascript复制import java.util.function.Function;
public class Demo1 {
public static void main(String[] args) {
//方法1
method1(100,(Integer i) -> String.valueOf(i 500));
//方法2
method2("200",(String s) -> Integer.parseInt(s));
//方法3
method3("200",(String s) -> Integer.parseInt(s),(Integer i) -> String.valueOf(i 500));
}
//方法1:把int类型 500转化为字符串类型
private static void method1(int i, Function<Integer,String> fun){
String s = fun.apply(i);
System.out.println(s);
}
//方法2:把字符串类型转化为int类型
private static void method2(String s, Function<String,Integer> fun){
int i = fun.apply(s);
System.out.println(s);
}
//方法3:把字符串类型,转化为int类型,int类型 500后转化为字符串类型输出
private static void method3(String s, Function<String,Integer> fun1,Function<Integer ,String> fun2){
String str = fun1.andThen(fun2).apply(s);
System.out.println(str);
}
}
练习:
- 我们给出String s = “胡桃,20”;
- 按下列步骤:
- 将字符串截取到数字年龄部分
- 将上一步的字符串转换为int类型
- 将上一步的int类型 70后得到结果并输出
- 请通过Function接口实现函数拼接
import java.util.function.Function;
public class Demo2 {
public static void main(String[] args) {
//调用方法:
printInfo("胡桃,20",(String s) -> s.split(",")[1],(String s) -> Integer.parseInt(s),(Integer i) -> i 70);
}
//方法
private static void printInfo(String s, Function<String, String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3){
System.out.println(fun1.andThen(fun2).andThen(fun3).apply(s));
}
}
结束语
好的,关于函数式接口的内容就到这里