版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/84678453
简介
JDK 1.8 API包含了很多内建的函数式接口。之所以提供这些接口,是因为它们有比较多的使用场景,通过结合使用lambda
表达式,我们可以很方便地利用这些接口将一些逻辑作为变量传递甚至组合起来实现更为复杂的逻辑,就像我们将一些普通类对象作为变量传递或者组合起来一样方便。
这里我们对一些常用的函数式接口给出一些简单的使用例子,方便你理解这些接口的意义,也在想使用它们的时候,知道怎样使用。
接口 | 介绍 |
---|---|
Consumer<T> |
消费函数:接收一个类型为T 的参数,基于它进行某种计算,但并不返回任何结果 |
Predicate<T> |
一元断言函数/一元谓词函数:接收一个类型为T 的参数,进行某种断言计算,返回一个类型为boolean 的结果 |
Function<T, R> |
一元函数:接收一个类型为T 的参数,进行某种计算,返回一个类型为R 的结果 |
BiFunction<T, U, R> |
二元函数:接收两个参数,一个类型为T ,一个类型为U ,进行某种计算,返回一个类型为R 的结果 |
Supplier<T> |
提供者函数:经过某种计算,提供一个类型为T 的对象,但是不需要参数该接口在一些需要惰性求值的场合非常实用。 比如有些结果对象计算非常复杂耗时但却能保持一段时间不变,这种情况下你就可以在首次 get() 调用时才计算和创建结果数据对象,将其缓存后返回该结果对象,之后再次 get() 时都可以复用已经缓存的对象 |
UnaryOperator |
一元运算符::接收一个类型为T 的参数,返回一个同类型的结果可以由 Function<T,R> 实现同样功能,实际上继承自 Function<T,R> 并且要求其中T ,R 相同 |
BinaryOperator |
二元运算符:接受两个类型都是T 的参数,返回一个同类型的结果可以由 BiFunction<T,U,R> 实现同样功能,实际上继承自 BiFunction<T,U,R> 并且要求其中T ,U ,R 相同 |
代码示例
package test.functional;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.*;
/**
* Using Java 8 Functional interfaces as lambda expressions
*/
@Slf4j
public class Java8FunctionalDemo<T> {
/**
* 输入一个指定类型的参数,基于此参数进行某种计算,但是并不返回任何结果
*/
public static void demoConsumer() {
Consumer<List<String>> counter = list -> {
int number = list.size();
log.info("Consumer<T>-The list {} has {} elements", list, number);
};
String[] words = {"Tom", "and", "Jerry"};
counter.accept(Arrays.asList(words));
}
/**
* Function 函数式接口, 输入指定类型的参数,经过计算,
* 返回另外某个指定类型的结果。 输入参数的类型和返回结果
* 的类型可以相同也可以不同。
*/
public static void demoFunction() {
{//例子: 计算某个整数的平方
// 特点 : 入参类型T和结果类型R可以一样
Function<Integer, Integer> square = i -> i * i;
int root = 9;
int result = square.apply(root);// 注意这里入参类型是Integer,返回值类型也是 Integer
log.info("Function<T,T>-Square of {} is : {}", root, result);
}
{// 例子 : 求字符串的长度
// 特点 : 入参类型T和结果类型R可以不一样
Function<String, Integer> length = s -> s.length();
String string = "Hello World!";
int result = length.apply(string); // 注意这里入参类型是String,返回结果类型是 Integer
log.info("Function<T,R>-Length of string '{}; is : {}", string, result);
}
}
/**
* BiFunction 函数式接口, 输入指定类型为T,Y的两个参数,经过计算,
* 返回另外某个指定类型为R的结果。 两个输入参数的类型和返回结果的类型三者
* 可以相同也可以不同。
*/
public static void demoBiFunction() {
{//例子: 计算两个整数的和
// 特点 : 入参类型T和结果类型T一样
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
int a = 9;
int b = 10;
int result = sum.apply(a, b);// 注意这里两个入参类型都是Integer,返回值类型也是 Integer
log.info("BiFunction<T,T,T>-Sum of {},{} is : {}", a, b, result);
}
{// 例子 : 获取一组名字中某种姓氏的名字的个数
BiFunction<List<String>, String, Long> count = (data, filter) -> {
long counter = data.stream().filter((e) -> e.startsWith("王")).count();
return counter;
};
String[] names = {"王刚", "谢胜武", "张三丰", "刘德财", "张德帅", "王梦云"};
String familyName = "王";
// 注意这里 T,U,R 分别是 : List<String>,String,Long
long counter = count.apply(Arrays.asList(names), familyName);
log.info("BiFunction<T,U,R>-这群人{}里面,老{}家来了{}个人", names, familyName, counter);
}
}
static void demoSupplier() {
// 不需要提供参数,每次总是返回同一个常量
Supplier<String> constValueSupplier = () -> "hello world";
log.info("Supplier<T>-提供常量值 : {}", constValueSupplier.get());
//替代不接受参数的工厂方法
Supplier<LocalDateTime> factorySupplier = () -> LocalDateTime.now();
log.info("Supplier<T>-代替工厂方法,提供对象 : {}", factorySupplier.get());
//java 的new 方法不接受参数但是能返回一个结果对象,所以可以用一个 supplier替代
Supplier<Date> asNewSupplier = Date::new;
log.info("Supplier<T>-代替类的new方法,提供对象 : {}", asNewSupplier.get());
}
/**
* 一元操作符,输入一个指定类型为T的参数,返回一个同样类型的结果,
* 实际上继承自Function<T,R>,只是限制了其中的T,R必须相同
*/
public static void demoUnaryOperator() {
{//例子: 计算某个整数的平方
// 特点 : 入参类型T和结果类型T一样
UnaryOperator<Integer> square = i -> i * i;
int root = 9;
int result = square.apply(root);// 注意这里入参类型是Integer,返回值类型也是 Integer
log.info("UnaryOperator<T>-Square of {} is : {}", root, result);
}
}
/**
* 二元操作符,输入两个指定类型为T的参数,返回一个同样类型的结果,
* 实际上继承自BiFunction<T,U,R>,只是限制了其中的T,U,R必须相同
*/
public static void demoBinaryOperator() {
{//例子: 计算两个整数的和
// 特点 : 入参类型T和结果类型T一样
BinaryOperator<Integer> sum = (a, b) -> a + b;
int a = 9;
int b = 10;
int result = sum.apply(a, b);// 注意这里两个入参类型都是Integer,返回值类型也是 Integer
log.info("BinaryOperator<T>-Sum of {},{} is : {}", a, b, result);
}
}
/**
* 输入一个指定类型为T的参数,基于它执行某种断言逻辑,给出一个 true/false 结论
*/
public static void demoPredicate() {
{//例子: 判断入参表示的某种动物是否是狗
// 特点 : 入参类型T和结果类型T一样
Predicate<String> isDog = type -> type.equalsIgnoreCase("dog");
String animal1 = "dog";
boolean animal1IsDog = isDog.test(animal1);// 注意这里入参类型是String,返回值类型也是 boolean
log.info("Predicate<T>-{} is a dog : {}", animal1, animal1IsDog);
String animal2 = "cat";
boolean animal2IsDog = isDog.test(animal2);// 注意这里入参类型是String,返回值类型也是 boolean
log.info("Predicate<T>-{} is a dog : {}", animal2, animal2IsDog);
}
}
public static void main(String[] args) {
demoFunction();
demoBiFunction();
demoConsumer();
demoSupplier();
demoPredicate();
demoUnaryOperator();
demoBinaryOperator();
}
}
输出结果如下所示:
Function<T,T>-Square of 9 is : 81
Function<T,R>-Length of string 'Hello World!; is : 12
BiFunction<T,T,T>-Sum of 9,10 is : 19
BiFunction<T,U,R>-这群人[王刚, 谢胜武, 张三丰, 刘德财, 张德帅, 王梦云]里面,老王家来了2个人
Consumer<T>-The list [Tom, and, Jerry] has 3 elements
Supplier<T>-提供常量值 : hello world
Supplier<T>-代替工厂方法,提供对象 : 2018-12-01T22:38:15.799
Supplier<T>-代替类的new方法,提供对象 : Sat Dec 01 22:38:15 CST 2018
Predicate<T>-dog is a dog : true
Predicate<T>-cat is a dog : false
UnaryOperator<T>-Square of 9 is : 81
BinaryOperator<T>-Sum of 9,10 is : 19