Java 8 特性 —— 函数式接口

java

概述:接口中只有一个抽象方法。

函数式接口,即适用于函数式编程场景的接口。而 Java 中的函数式编程体现就是 Lambda,所以函数式接口就是可以适用于 Lambda 使用的接口。只有确保接口中有且仅有一个抽象方法,Java 中的 Lambda 才能顺利地进行推导。

备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实

底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部

类的“语法糖”,但是二者在原理上是不同的。

格式

只要确保接口中有且仅有一个抽象方法即可

修饰符 interface 接口名称 {

public abstract 返回值类型 方法名称(可选参数信息);

// 其他非抽象方法内容

}

@FunctionalInterface注解

与@Override 注解的作用类似,Java8 中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法(但是可以有多个非抽象方法),否则将会报错,如下图。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

自定义函数式接口

package com.boomoom;

/**

* 自定义函数式接口

* 使用@FunctionalInterface可以说明该接口是函数式接口,但是不加,如果接口中只有一个抽象方法,这个接口也是函数式接口

* 也就是说函数式接口不以注解的存在而存在

*/

@FunctionalInterface

public interface MyFunctionalInterface {

public abstract void show();

}

有参数,有返回值的自定义函数式接口

@FunctionalInterface

public interface Sumable {

int sum(int a, int b);

}

JDK1.8之后的某些函数式接口

JDK 1.8 之前已有的函数式接口:

java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

JDK 1.8 新增加的函数接口:
java.util.function

java.util.function 包路径下包含了很多类,用来支持 Java 的函数式编程。选取几个接口示例详解。

supplier生产数据函数式接口

目的是生产数据。

目前好像看不出来有什么用,但是好像和 jdk8 的 Stream 流有关。举个小例子:

package com.boomoom;

import java.util.function.Supplier;

/**

* 使用supplier函数式接口求数组的最大值

*/

public class ArrMaxValue {

public static int getMaxValue(Supplier<Integer> sup){

return sup.get();

}

public static void main(String[] args) {

// 创建数组

int[] arr = {100,20,50,30,99,101,-50};

int maxValue = getMaxValue(()->{

int max = arr[0];

for (int i : arr) {

if(i > max){

max = i;

}

}

return max;

});

System.out.println("数组中的最大值为:" + maxValue); // 数组中的最大值为:101

}

}

Consumer消费数据函数式接口

这个方法是用来消费数据的,如何消费,消费规则自己定义。

package com.boomoom;

import java.util.function.Consumer;

/**

* 使用Consumer函数式接口实现格式化输出

*/

public class ConsumerDemo {

public static void printInfo(String[] strArr, Consumer<String> con1, Consumer<String> con2) {

for (int i = 0; i < strArr.length; i++) {

con1.andThen(con2).accept(strArr[i]);

}

}

public static void main(String[] args) {

String[] strArr = {"迪丽热巴,女", "郑爽,女", "杨紫,女"};

printInfo(strArr, (message) -> {

System.out.print("姓名:" + message.split(",")[0] + "。 ");

}, (message) -> {

System.out.println("性别:" + message.split(",")[1] + "。");

});

}

}

Predicate判断函数式接口

Predicate 接口中包含一个抽象方法:boolean test(T t) 。用于条件判断的场景。

默认方法:

package com.boomoom;

import java.util.ArrayList;

import java.util.function.Predicate;

public class PredicateDemo {

/**

* 检查数组中的元素是否符合要求,满足要求加入List中并返回

* @param arr 需要判断的数组

* @param pre1 判断接口1,判断性别是否为女

* @param pre2 判断接口2,判断姓名长度是否大于2

* @return

*/

public static ArrayList<String> checkStar(String[] arr, Predicate<String> pre1, Predicate<String> pre2){

ArrayList<String> arrayList = new ArrayList<>();

for (int i = 0; i < arr.length; i++) {

boolean test = pre1.and(pre2).test(arr[i]);

if (test) {

arrayList.add(arr[i]);

}

}

return arrayList;

}

public static void main(String[] args) {

// 创建数组

String[] arr = {"迪丽热巴,女","杨洋,男","李溪芮,女","郑爽,女"};

// 调用方法(Lambda表达式可以简化)

ArrayList<String> list = checkStar(arr,(str)-> str.split(",")[1].equals("女"),

(str)-> str.split(",")[0].length() > 2);

// 遍历集合

for (String elem : list) {

System.out.print(elem + " ");

}

}

}

Function类型转换函数式接口

Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。

Function 接口中有一个默认的andThen 方法,用来进行组合操作。

package com.boomoom;

import java.util.function.Function;

public class FunctionDemo {

/**

* 将String分割,获得第二个元素,将数据转化为int,int数据加1000,再将int转化为String

* @param str 转化的数据

* @param fun1 String -> String

* @param fun2 String -> Integer

* @param fun3 Integer -> String

* @return 最后的String

*/

public static String convert(String str,

Function<String,String> fun1,

Function<String, Integer> fun2,

Function<Integer,String> fun3){

return fun1.andThen(fun2).andThen(fun3).apply(str);

}

public static void main(String[] args) {

String str = convert("迪丽热巴,24",(s)->{

return s.split(",")[1];

},(s)->{

return Integer.parseInt(s) + 1000;

}, String::valueOf);

System.out.println(str);

}

}

参考:http://www.runoob.com/java/java8-functional-interfaces.html

 https://www.cnblogs.com/wadmwz/p/9384660.html

概述:接口中只有一个抽象方法。

函数式接口,即适用于函数式编程场景的接口。而 Java 中的函数式编程体现就是 Lambda,所以函数式接口就是可以适用于 Lambda 使用的接口。只有确保接口中有且仅有一个抽象方法,Java 中的 Lambda 才能顺利地进行推导。

备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实

底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部

类的“语法糖”,但是二者在原理上是不同的。

格式

只要确保接口中有且仅有一个抽象方法即可

修饰符 interface 接口名称 {

public abstract 返回值类型 方法名称(可选参数信息);

// 其他非抽象方法内容

}

@FunctionalInterface注解

与@Override 注解的作用类似,Java8 中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法(但是可以有多个非抽象方法),否则将会报错,如下图。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

自定义函数式接口

package com.boomoom;

/**

* 自定义函数式接口

* 使用@FunctionalInterface可以说明该接口是函数式接口,但是不加,如果接口中只有一个抽象方法,这个接口也是函数式接口

* 也就是说函数式接口不以注解的存在而存在

*/

@FunctionalInterface

public interface MyFunctionalInterface {

public abstract void show();

}

有参数,有返回值的自定义函数式接口

@FunctionalInterface

public interface Sumable {

int sum(int a, int b);

}

JDK1.8之后的某些函数式接口

JDK 1.8 之前已有的函数式接口:

java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

JDK 1.8 新增加的函数接口:
java.util.function

java.util.function 包路径下包含了很多类,用来支持 Java 的函数式编程。选取几个接口示例详解。

supplier生产数据函数式接口

目的是生产数据。

目前好像看不出来有什么用,但是好像和 jdk8 的 Stream 流有关。举个小例子:

package com.boomoom;

import java.util.function.Supplier;

/**

* 使用supplier函数式接口求数组的最大值

*/

public class ArrMaxValue {

public static int getMaxValue(Supplier<Integer> sup){

return sup.get();

}

public static void main(String[] args) {

// 创建数组

int[] arr = {100,20,50,30,99,101,-50};

int maxValue = getMaxValue(()->{

int max = arr[0];

for (int i : arr) {

if(i > max){

max = i;

}

}

return max;

});

System.out.println("数组中的最大值为:" + maxValue); // 数组中的最大值为:101

}

}

Consumer消费数据函数式接口

这个方法是用来消费数据的,如何消费,消费规则自己定义。

package com.boomoom;

import java.util.function.Consumer;

/**

* 使用Consumer函数式接口实现格式化输出

*/

public class ConsumerDemo {

public static void printInfo(String[] strArr, Consumer<String> con1, Consumer<String> con2) {

for (int i = 0; i < strArr.length; i++) {

con1.andThen(con2).accept(strArr[i]);

}

}

public static void main(String[] args) {

String[] strArr = {"迪丽热巴,女", "郑爽,女", "杨紫,女"};

printInfo(strArr, (message) -> {

System.out.print("姓名:" + message.split(",")[0] + "。 ");

}, (message) -> {

System.out.println("性别:" + message.split(",")[1] + "。");

});

}

}

Predicate判断函数式接口

Predicate 接口中包含一个抽象方法:boolean test(T t) 。用于条件判断的场景。

默认方法:

package com.boomoom;

import java.util.ArrayList;

import java.util.function.Predicate;

public class PredicateDemo {

/**

* 检查数组中的元素是否符合要求,满足要求加入List中并返回

* @param arr 需要判断的数组

* @param pre1 判断接口1,判断性别是否为女

* @param pre2 判断接口2,判断姓名长度是否大于2

* @return

*/

public static ArrayList<String> checkStar(String[] arr, Predicate<String> pre1, Predicate<String> pre2){

ArrayList<String> arrayList = new ArrayList<>();

for (int i = 0; i < arr.length; i++) {

boolean test = pre1.and(pre2).test(arr[i]);

if (test) {

arrayList.add(arr[i]);

}

}

return arrayList;

}

public static void main(String[] args) {

// 创建数组

String[] arr = {"迪丽热巴,女","杨洋,男","李溪芮,女","郑爽,女"};

// 调用方法(Lambda表达式可以简化)

ArrayList<String> list = checkStar(arr,(str)-> str.split(",")[1].equals("女"),

(str)-> str.split(",")[0].length() > 2);

// 遍历集合

for (String elem : list) {

System.out.print(elem + " ");

}

}

}

Function类型转换函数式接口

Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。

Function 接口中有一个默认的andThen 方法,用来进行组合操作。

package com.boomoom;

import java.util.function.Function;

public class FunctionDemo {

/**

* 将String分割,获得第二个元素,将数据转化为int,int数据加1000,再将int转化为String

* @param str 转化的数据

* @param fun1 String -> String

* @param fun2 String -> Integer

* @param fun3 Integer -> String

* @return 最后的String

*/

public static String convert(String str,

Function<String,String> fun1,

Function<String, Integer> fun2,

Function<Integer,String> fun3){

return fun1.andThen(fun2).andThen(fun3).apply(str);

}

public static void main(String[] args) {

String str = convert("迪丽热巴,24",(s)->{

return s.split(",")[1];

},(s)->{

return Integer.parseInt(s) + 1000;

}, String::valueOf);

System.out.println(str);

}

}

以上是 Java 8 特性 —— 函数式接口 的全部内容, 来源链接: utcz.com/z/391150.html

回到顶部