Java函数式接口
在Java1.8引入,只且仅有一个抽象接口方法的接口称为函数式接口,当然接口中可以包含其他方法(默认、静态、私有),用@FunctionalInterface注解。像常用的Callable
下面介绍一个简单的自定义的函数接口和四种常用的函数式接口的使用
自定义函数式接口
package base._interface.simple_method_interface;
public class Demo {
public static void main(String[] args) {
useInterfaceMethod(new SimpleMethodInterfaceImp()); // 使用函数接口的实现类
useInterfaceMethod(new SimpleMethodInterface() { // 本质上和上面一样,只不过是一个匿名类
@Override
public void method() {
System.out.println("use anonymous inner class to say hello world");
}
});
useInterfaceMethod(() -> {
System.out.println("use lambda to say hello world"); // 用Lambda
});
}
public static void useInterfaceMethod(SimpleMethodInterface simpleMethodInterface) {
simpleMethodInterface.method();
}
}
class SimpleMethodInterfaceImp implements SimpleMethodInterface {
@Override
public void method() {
System.out.println("use implement class to say hello world");
}
}
/**
* @FunctionalInterface 该注解表示接口Functional是否为函数式接口
* 是则编译通过,否则不通过
*/
@FunctionalInterface
interface SimpleMethodInterface {
public abstract void method();
}
四种常用的函数式接口
名称 | 唯一抽象方法 | 描述 |
---|---|---|
Consumer< T > | void accept(T t); | 接收一个参数,无返回值,即数据消费接口 |
Predicate< T > | boolean test(T t); | 接受一个参数,返回布尔值,即数据判断接口 |
Supplier< T > | T get(); | 无参数,有返回值,即数据获取接口 |
Function< T, R > | R apply(T t); | 接受T类型参数,返回R类型结果,即数据映射接口 |
package base._interface.functional_method_interface;
import java.util.function.Consumer; // 数据消费接口
import java.util.function.Function; // 数据映射接口
import java.util.function.Predicate; // 数据判断接口
import java.util.function.Supplier; // 数据获取接口
public class Demo {
public static void main(String[] args) {
supplierTest();
consumerTest();
predicateTest();
functionTest();
}
public static void consumerTest() {
// 怎么消费由lambda具体实现
consumer(8, (integer) -> {
System.out.println("integer:" + integer);
});
consumer(8, (integer) -> {
System.out.println("integer*integer:" + integer * integer);
});
}
public static void supplierTest() {
// 获取什么的结果由lambda具体实现
int[] arr = {1, 3, 4, 5, 1, 4, 9};
// 获取最大值
int max = supplier(() -> {
int maxNum = arr[0];
for (int value : arr) {
if (value >= maxNum) {
maxNum = value;
}
}
return maxNum;
});
System.out.println("max number:" + max);
// 获取最小值
int min = supplier(() -> {
int minNum = arr[0];
for (int value : arr) {
if (value <= minNum) {
minNum = value;
}
}
return minNum;
});
System.out.println("min number:" + min);
}
public static void predicateTest() {
boolean ret = predicate(8, num -> num > 5);
System.out.println(ret);
ret = predicate(8, num -> num < 5);
System.out.println(ret);
}
public static void functionTest() {
int num = 9;
String res = function(num, (str) -> num + ""); // 整型数字转换为字符串形式的数字
System.out.println(res);
}
// 消费数据接口
public static void consumer(int num, Consumer<Integer> consumer) {
consumer.accept(num);
}
// 获取数据接口
public static int supplier(Supplier<Integer> supplier) {
return supplier.get();
}
// 判断数据接口
public static boolean predicate(int num, Predicate<Integer> predicate) {
return predicate.test(num);
}
// 数据映射接口
public static String function(int num, Function<Integer, String> function) {
return function.apply(num);
}
}
应用场景
结合流Stream的使用可以优化代码。
package base._interface.stream;
import java.util.List;
import java.util.stream.Stream;
/**
* JDK1.8开始加入Stream流操作
* 所有Collection集合都可以通过stream获取流或者通过Stream.of,数组也可以
* Stream<Integer> s = Stream.of(1,2,3,4);
* Integer[] arr = {1,2,3,4};
* Stream<Integer> arrStream = Stream.of(arr);
* 注意:流只能使用一次,使用后关闭,顾名思义流水线
* 优点:可以一次性数据进行多次处理,不需要每次都要遍历数据,并且代码可以很简洁
*
* 常用的流方法:
* map映射,一个流转化为另一个流
* sorted升序排序
* count统计流中元素的个数
* limit(n)取前n个流中的元素
* skip则和limit相反,跳过n个元素,取后面的元素
* Stream中的静态方法,contact连接两个流
*/
public class Demo {
public static void main(String[] args) {
}
public static void streamTest() {
List<String> list = List.of("张三", "李四", "张三丰", "张麻子");
Stream<String> stream = list.stream();
stream
.filter(name -> name.startsWith("张")) // 过滤不为张的姓名 这里使用的就是Predicate数据判断接口
.filter(name -> name.length() == 3) // 过滤长度不为3的姓名
.forEach(System.out::println); //这里使用的就是Consumer数据判断接口
// error:stream has already been operated upon or closed
//stream.forEach(name-> System.out.println(name));
Stream<String> strStream = Stream.of("1", "3", "2", "4", "5");
Stream<Integer> intStream = strStream.map(Integer::parseInt); // 方法引用
intStream.sorted().limit(4).skip(1).forEach(System.out::println); // 先排序,再限制流中的个数为4,在跳过第1个元素
}
}