目录
一、Supplier 接口
1、将 Supplier 直接使用
2、将 Supplier 使用生成对象
3、将 Supplier 做为方法的参数
二、Consumer 接口
1、直接使用 Consumer 对象
2、Consumer 做为参数
3、使用 Consumer 做为参数
三、Predicate 接口
1、test()方法演示
2、默认方法 and()
3、默认方法 or()
4、默认方法 negate()
5、静态方法 isEqual ()
6、Predicate 的应用示例
四、Function 接口
1、抽象方法:apply()
2、默认方法:andThen()
3、默认方法:compose()
五、BinaryOperator 接口
1、方法的演示:apply()
2、BinaryOperator 接口做为方法参数
3、静态方法的演示
六、UnaryOperator 接口
UnaryOperator 使用方法的参数
七、常用的函数式接口小结
Java8函数式接口
接口 | 参数 | 返回 | 中文 | 实例 |
Supplier | None | T | 提供者 | 工厂方法创建对象 |
Consumer | T | None | 消费者 | 消费一个数据,无返回 |
Predicate | T | boolean | 判断/谓词 | 对指定条件进行测试 |
Function | T | R | 函数 | 根据一个参数得到另一个参数值 |
Supplier 接口代表一个结果的提供者。
Supplier 接口是用来生成数据的,数据的类型通过泛型参数给定,使用 get()方法获得返回值。
接口的源码如下:
@FunctionalInterface
public interface Supplier {
/**
* 得到一个结果,返回 T 对象
* @return a result
*/
T get();
}
Supplier 接口中的方法
T get() 获得指定类型的数据
案例需求:get()方法的基本使用,在 Supplier 接口中 get 方法返回一个字符串。
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
//使用 Lambda 创建 Supplier 对象
Supplier supplier = () -> "Hello Java!";
//输出它的值
System.out.println(supplier.get());
}
}
// 输出
// Hello Java!
案例需求:
下面的例子演示了如何通过调用一个静态方法,生成一个员工对象返回。使用构造方法做为 Supplier 参数的引用。
案例步骤:
因为 Employee 对象是私有的,外部类无法直接实例化员工对象。
调用 Supplier 的 get()方法来生成员工对象,这样做的目的是可以控制员工对象的生成方式,类似于工厂模式。
public class LambdaTest {
public static void main(String[] args) {
//使用 Lambda 传入 Supplier 对象,将生成一个员工对象
//此时仅仅是实例化了接口并未执行里面代码
Supplier supplier = ()->new Employee();
//输出员工对象
System.out.println(supplier.get());
}
//员工类
private static class Employee {//注意static
@Override
public String toString() {
return "我是员工";
}
}
}
// 输出
// 我是员工
需求说明:求数组中的最大值,使用 Supplier 接口作为方法参数类型,通过 Lambda 表达式求出 int 数组中的最大值。
需求分析:
public class LambdaTest {
public static void main(String[] args) {
int[] arr = {12, 68, 10, 2, 99, 313, 46};
// 调用 getMax 方法获得最大值,Lambda 相当于方法体
int num = getMax(() -> {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
return max;
});
//输出最大值
System.out.println("最大值是:" + num);
}
//使用 Supplier 做为参数
public static int getMax(Supplier supplier) {
return supplier.get();
}
}
// 输出
// 最大值是:313
Consumer 接口代表接受单一的输入变量而且没有返回值的一类操作。 它的作用和 Supplier 相反,是消费一个数据的,消费的数据类型需要通过泛型指定。
源代码如下:
@FunctionalInterface
public interface Consumer {
/**
* 接受 t 对象,无返回值
*/
void accept(T t);
/**
* 默认的组合方法,参数和返回值都是 Consumer 类型
* 先调用自己的 accept()方法,再调用参数的 accept()方法
*/
default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Consumer 接口中的方法
void accept(T t) 接受对给定的参数进行操作。
Consumer 接口中的默认方法:
default Consumer andThen(Consumer after)
如果一个方法的参数和返回值全都是 Consumer
消费一个数据的时候,首先做一个操作,然后再做另一个操作,两个操作依次执行,实现一种组合操作。而这个方法就是 Consumer 接口中的默认方法 andThen。
实现步骤:
public class LambdaTest {
public static void main(String[] args) {
//创建 Consumer 对象,打印传入的变量 t
Consumer consumer = t -> System.out.println(t);
//调用 Consumer 中的方法
consumer.accept("Hello Lambda");
}
}
// 输出
// Hello Lambda
List 和 Set 集合中遍历的 forEach 方法它的参数就是 Consumer,请看下面的代码:
案例需求:
public class LambdaTest {
public static void main(String[] args) {
//将数组转成 List 对象
List names = Arrays.asList("孙悟空", "猪八戒", "白骨精", "嫦娥");
//打印每一个字符串,forEach 的参数就是 Consumer
names.forEach(t -> System.out.println(t));
}
}
// 输出
//孙悟空
//猪八戒
//白骨精
//嫦娥
分析 forEach()方法的源代码
default void forEach(Consumer super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
这是定义在 java.lang.Iterable 接口中的默认方法,参数就是 Consumer 对象,方法体内对当前集合使用 for遍历,this 就是集合对象。每次对一个元素调用 accept()方法。而我们外部调用的代码中对 accept()方法进行了实现,输出了每个元素。
public static T requireNonNull(T obj) 静态方法,JDK7 中新增的方法,判断传入的对象是否为 NULL,如果是 NULL 则抛出异常,不为 NULL 则返回对象本身。常用于方法或构造方法中传入对象参数的校验。
default Consumer andThen(Consumer super T> after) {
//判断 after 是否为 null
Objects.requireNonNull(after);
//先调用自己的 accept()方法,再调用参数的 accept()方法
return (T t) -> { accept(t); after.accept(t); };
}
要想实现组合,需要两个或多个 Lambda 表达式,而 andThen 的语义正是执行“一步接一步”操作。
案例需求:将字符串 Hello 首先打印大写的 HELLO,然后打印小写的 hello
实现步骤:
public class LambdaTest {
public static void main(String[] args) {
//打印大写
Consumer c1 = s -> System.out.println(s.toUpperCase());
//打印小写
Consumer c2 = s-> System.out.println(s.toLowerCase());
//调用方法
c1.andThen(c2).accept("Hello Consumer");
}
}
// 输出
// HELLO CONSUMER
// hello consumer
需求说明:
格式化打印信息,下面的字符串数组当中存有多条信息,请按照格式“姓名:XX。性别:XX。”的格式将信息打印出来。要求将打印姓名的动作作为第一个 Consumer 接口的 Lambda 实例,将打印性别的动作作为第二个Consumer 接口的 Lambda 实例,将两个 Consumer 接口按照顺序“拼接”到一起。以下数组共 5 个元素,每个元素包含 2 项信息用逗号分隔。
String[] arr = { "张飞,男", "貂蝉,女", "曹操,男","孙尚香,女","小乔,女" };
实现步骤
public class LambdaTest {
public static void main(String[] args) {
String[] arr = {"张飞,男", "貂蝉,女", "曹操,男","孙尚香,女"};
//这里的 s 表示数组中的每个元素
printInfo(arr,
s ->System.out.println("姓名:" + s.split(",")[0]),
s ->System.out.println("性别:" + s.split(",")[1]));
}
public static void printInfo(String[] arr, Consumer name, Consumer gender) {
for (String s : arr) {
name.andThen(gender).accept(s);
System.out.println("------------------");
}
}
}
Predicate 中文意思为谓语,"我是一个程序员","是"或"不是"就是谓语。
它代表只有一个变量的函数,返回 boolean 类型。有时候我们需要进行某种判断,从而得到一个 boolean 值的结果。可以使用 java.util.function.Predicate接口。
@FunctionalInterface
public interface Predicate {
/**
* 抽象方法,对 t 进行测试,返回 boolean 类型
*/
boolean test(T t);
/**
* 组合方法,将当前的谓语与另一个谓语进行短路的与操作,返回一个谓语对象
*/
default Predicate and(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* 对当前的谓语进行逻辑非操作,返回一个谓语对象
*/
default Predicate negate() {
return (t) -> !test(t);
}
/**
* 组合方法,将当前的谓语与另一个谓语进行短路的或操作,返回一个谓语对象
*/
default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* 静态方法,判断 test(object)方法传入的对象是否与参数 targetRef 对象相等
*/
static Predicate isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
Predicate 接口中的方法
boolean test(T t) 对 t 进行指定条件的测试,返回 boolean 类型
案例需求:判断 test("字符串")方法给定的参数长度是否大于 5
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
//创建一个 Predicate 谓语对象,boolean test(T t)方法接收字符串类型,返回 boolean 类型
Predicate predicate = s -> s.length() > 5;
//两次调用 test 方法看运行结果
System.out.println("Hello 的长度是否大于 5:" + predicate.test("Hello"));
System.out.println("Predicate 的长度是否大于 5:" + predicate.test("Predicate"));
}
}
// 执行结果
// Hello 的长度是否大于 5:false
// Predicate 的长度是否大于 5:true
既然是条件判断,就会存在与、或、非三种常见的逻辑关系。 其中将两个 Predicate 条件使用“与”逻辑连接起来实现“并且”的效果时,可以使用 default 方法 and。 这个默认方法接收一个 Predicate 参数,返回一个 Predicate参数。
其 JDK 源码为:
/**
* 组合方法,将当前的谓语与另一个谓语进行短路的与操作,返回一个谓语对象
*/
default Predicate and(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
and 方法演示示例:
案例需求:判断一个字符串是否包含指定的字符串:既包含大写“H”,又要包含大写“W”
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
//创建 2 个需要判断的字符串
String s1 = "Hello world";
String s2 = "Hello World";
// 使用 Lambda 表达式,创建两个 Predicate 对象
//判断 s 是否包含 H
Predicate p1 = s -> s.contains("H");
//判断 s 是否包含 W
Predicate p2 = s -> s.contains("W");
//调用 and 方法
System.out.println(s1 + "是否包含 H 和 W:" + p1.and(p2).test(s1));
System.out.println(s2 + "是否包含 H 和 W:" + p1.and(p2).test(s2));
}
}
// 输出结果
// Hello world是否包含 H 和 W:false
// Hello World是否包含 H 和 W:true
与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”操作。 这个默认方法接收一个 Predicate 参数,返回一个 Predicate 参数。
JDK 源码为:
/**
* 组合方法,将当前的谓语与另一个谓语进行短路的或操作,返回一个谓语对象
*/
default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
or 方法演示示例:
案例需求:判断一个字符串的长度大于 10 或者小于 5
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
//创建三个字符串
String s1 = "Hello World"; //大于 10
String s2 = "Java"; //小于 5
String s3 = "I am boy"; //既不大于 10,又不小于 5
//使用 Lambda 创建 2 个 Predicate 接口对象
Predicate p1 = s -> s.length() > 10;
Predicate p2 = s -> s.length() < 5;
//输出每个字符串的测试结果
System.out.println(s1 + "=" + p1.or(p2).test(s1));
System.out.println(s2 + "=" + p1.or(p2).test(s2));
System.out.println(s3 + "=" + p1.or(p2).test(s3));
}
}
// 输出结果
// Hello World=true
// Java=true
// I am boy=false
“与”、“或”已经了解了,剩下的“非”(取反)也会简单。方法没有参数,返回值为 Predicate。
默认方法 negate的 JDK 源代码为:
/**
* 对当前的谓语进行逻辑非操作,返回一个谓语对象
*/
default Predicate negate() {
return (t) -> !test(t);
}
从实现中很容易看出,它是执行了 test 方法之后,对结果 boolean 值进行“!”取反而已。
要在 test 方法调用之前调用 negate 方法,正如 and 和 or 方法一样。
案例需求:判断年龄是否小于 18 岁,将判断的结果取反。
案例步骤
public class LambdaTest {
public static void main(String[] args) {
int age1 = 25; //25 岁
int age2 = 15; //15 岁
Predicate predicate = (a) -> a < 18; //判断是否小于 18 岁
System.out.println(age1 + "小于 18 岁,取反:" + predicate.negate().test(age1));
System.out.println(age2 + "小于 18 岁,取反:" + predicate.negate().test(age2));
}
}
// 执行结果
// 25小于 18 岁,取反:true
// 15小于 18 岁,取反:false
Predicate 中唯一的静态方法,方法的参数是两个 Object 类型,返回一个 Predicate 类型。
作用:根据 Objects.equals(Object, Object)方法比较两个参数是否相等,
一个对象通过 isEqual()传入,另一个对象通过 test()传入。
// java.util.Objects 类中的方法 说明
public static boolean equals(Object a,Object b)
作用:用于比较两个对象是否相等
参数:a 和 b 是要比较的两个对象
返回:如果两个对象相等,则返回 true,否则返回 false
JDK 源代码为:
/**
* 静态方法,判断 test(object)方法传入的对象是否与参数 targetRef 对象相等
*/
static Predicate isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
案例需求:比较两个字符串是否相等
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
//通过静态方法直接返回 Predicate 对象
Predicate predicate = Predicate.isEqual("newboy");
//调用 test()方法传入另两个字符串分别比较
System.out.println("两个字符串是否相等:" + predicate.test("newboy"));
System.out.println("两个字符串是否相等:" + predicate.test("NewBoy"));
}
}
// 执行结果
// 两个字符串是否相等:true
// 两个字符串是否相等:false
需求说明:
集合当中有多条“姓名+性别”的信息如下:"张飞,男", "貂蝉,女", "曹操,男","孙尚香,女","小乔,女",请通过 Predicate 接口的 and 组合方法,将符合要求的字符串筛选到集合 ArrayList 中,需要同时满足两个条件:
开发步骤:
public class LambdaTest {
public static void main(String[] args) {
//从数组中创建一个 List 集合
List list = Arrays.asList("张飞,男", "貂蝉,女", "曹操,男","孙尚香,女","小乔,女");
//创建第 1 个 Predicate 判断条件:使用逗号分隔的第 0 个元素姓名长度是 2
Predicate pname = s -> s.split(",")[0].length() ==2;
//创建第 2 个 Predicate 判断条件:使用逗号分隔的第 1 个元素性别等于女
Predicate pgender = s-> s.split(",")[1].equals("女");
//创建一个新的 List 集合
List infos = new ArrayList<>();
//使用 Lamba 中的 forEach()遍历上面的 List 集合
//使用 Predicate 中的 and 和 test 方法判断每个元素
list.forEach(s -> {
//两个都为真才添加到集合中
if (pname.and(pgender).test(s)) {
infos.add(s);
}
});
//创建第 1 个 Consumer 接口,输出使用逗号分隔的第 0 个元素姓名
Consumer cname = s -> System.out.println("姓名:" + s.split(",")[0]);
//创建第 2 个 Consumer 接口,输出使用逗号分隔的第 1 个元素性别
Consumer cgender = s -> System.out.println("性别:" + s.split(",")[1]);
//使用 Lamba 中的 forEach()遍历,输出过滤后的集合
infos.forEach(s -> {
//使用 Consumer 接口中的 andThen 和 accept 方法,每输出一个元素隔一条线
cname.andThen(cgender).accept(s);
System.out.println("---------------");
});
}
}
// 输出结果
姓名:貂蝉
性别:女
---------------
姓名:小乔
性别:女
---------------
Function接口:
根据一个参数得到另一个参数值,前面称为计算的参数,后面称为计算的结果。
有进有出,所以称为“函数 Function”。
类似于数学中的函数,通过一个变量求出另一个变量的值。如:f(x) = 2x+3
以下是它的 Java 源代码:
// 代表通过一个变量求出另一个变量的结果的函数
@FunctionalInterface
public interface Function {
/**
* 对给定的变量 t 进行计算,得到返回的结果 R
*/
R apply(T t);
/**
* 默认组合方法,先计算当前函数,再计算传入的函数
*/
default Function compose(Function super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 默认组合方法,先计算传入的函数,再计算当前函数
*/
default Function andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 静态方法:总是返回它的输入变量
*/
static Function identity() {
return t -> t;
}
}
是java.util.function.Function 接口中的方法
R apply(T t); 对给定的变量 t 进行计算,得到返回的结果 R
apply 方法演示示例:
案例需求:将 Integer 类型转换为 String 类型,并且输出转换以后字符串的长度。
public class LambdaTest {
public static void main(String[] args) {
//创建一个 Function 对象
Function converter = i -> Integer.toString(i);
System.out.println("99 转成字符串的长度是:" + converter.apply(99).length());
System.out.println("1000 转成字符串的长度是:" + converter.apply(1000).length());
}
}
// 输出结果
99 转成字符串的长度是:2
1000 转成字符串的长度是:4
Function 接口中有一个默认的 andThen 方法,用来进行组合操作。
先计算当前函数,再计算传入的函数。两个函数依次执行。
andThen 方法的参数是 Function 对象,返回一个 Function 对象。
JDK 源代码:
/**
* 默认组合方法,先计算当前函数,再计算传入的函数
*/
default Function andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
案例需求:
连续进行两个操作:第 1 个操作是将字符串转换成为 int 数字,第 2 个操作将转换好的数字乘以 10。两个操作按照前后顺序组合到一起。
public class LambdaTest {
public static void main(String[] args) {
//用户输入一个字符串
System.out.println("请输入数字:");
Scanner input = new Scanner(System.in);
String str = input.nextLine();
//第 1 个函数将字符串转成整数
Function f1 = s -> Integer.parseInt(s);
//第 2 个函数将整数乘以 10 返回
Function f2 = i -> i * 10;
//调用 andThen 方法,并且输出结果
System.out.println("转成整数并乘以 10 以后的结果是:" + f1.andThen(f2).apply(str));
}
}
// 输出结果
请输入数字:
2
转成整数并乘以 10 以后的结果是:20
Function 中有一个与 andThen 非常类似的 compose 方法。
中文是"组成"的意思,方法参数是 Function,返回值是 Function,先运行参数的 apply 方法,再调用自己的 apply 方法。
其 JDK 源代码为:
/**
* 默认组合方法,先计算传入的函数,再计算当前函数
*/
default Function compose(Function super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 结合 andThen 方法的 JDK 源码实现进行对比,会发现 compose 方法的参数 Lamda 将会先执行。
所以二者只是先后顺序的不同而已。
compose 方法的演示
案例需求:
创建两个函数对象:1 个将字符串转成大写,1 个将字符串转成小写。分别使用 andThen 和 compose 方法组合调用,查看不同的计算结果。
开发步骤:
public class LambdaTest {
public static void main(String[] args) {
Function f1 = s -> s.toUpperCase();
Function f2 = s -> s.toLowerCase();
System.out.println("转成大写:" + f1.apply("Hello"));
System.out.println("转成小写:" + f2.apply("Hello"));
System.out.println("先转成大写,再转成小写:" + f1.andThen(f2).apply("Hello"));
System.out.println("先转成小写,再转成大写:" + f1.compose(f2).apply("Hello"));
}
}
// 执行结果
转成大写:HELLO
转成小写:hello
先转成大写,再转成小写:hello
先转成小写,再转成大写:HELLO
Function 的应用示例
需求说明:请使用 Function 进行函数拼接,按照顺序执行多个函数。
操作依次为:
开发步骤:
代码实现
public class LambdaTest {
public static void main(String[] args) {
//创建第 1 个 Function 对象,将字符串 20 取出,返回一个字符串
Function fun1 = s -> s.split(",")[1];
//创建第 2 个 Function 对象,将字符串转成整数,返回整数
Function fun2 = s -> Integer.parseInt(s);
//创建第 3 个 Function 对象,将整数加 100,返回计算结果
Function fun3 = num -> num + 100;
//调用 andThen 方法 2 次,apply 方法应用字符串,输出结果
System.out.println("计算结果:" + fun1.andThen(fun2).andThen(fun3).apply("赵丽颖,20"));
}
}
//输出结果
计算结果:120
BinaryOperator 表示对两个相同类型的操作数进行操作,产生相同类型的结果。
接口中的方法
static BinaryOperator maxBy(Comparator super T> comparator)
返回一个BinaryOperator ,它根据指定的Comparator返回两个元素中的较大Comparator 。
static BinaryOperator minBy(Comparator super T> comparator)
返回BinaryOperator返回根据指定的两个元件的较小的Comparator 。
这个接口中定义了两个静态方法,
BiFunction 是用于定义两个操作符的函数接口。
BiFunction接口中的方法
T apply(T t, T u); 从父接口 BiFunction 中继承下来的抽象方法,
传入两个参数 t 和 u 进行函数计算,返回计算的结果。
两个参数和返回值都是同一种类型。
default BiFunction andThen(Function super R,? extends V> after)
返回一个组合函数,首先将该函数应用于其输入,然后将after函数应用于结果。
如果任一函数的评估引发异常,则将其转发给组合函数的调用者。
案例需求:
使用 BinaryOperator 接口的 apply()方法,计算 2 个整数的和,并且输出结果。
案例步骤:
案例代码:
public class LambdaTest {
public static void main(String[] args) {
BinaryOperator operator = (m, n) -> m + n;
System.out.println("计算结果是:" + operator.apply(3, 5));
}
}
// 输出结果
计算结果是:8
静态方法
ublic static BinaryOperator minBy(Comparator comparator)
通过后面的 Comparator 比较器判断,返回两个元素中较小的元素
public static BinaryOperator maxBy(Comparator comparator)
通过后面的 Comparator 比较器判断,返回两个元素中较大的元素
Comparator 接口中的静态方法说明
naturalOrder() 按元素的自然排序的大小进行比较,返回一个 Comparator 对象
reverseOrder() 按元素的倒序大小进行比较,返回一个 Comparator 对象
案例需求:
有如下数组{2,1,3,5},对数组中的每个元素进行替换。替换算法如下:
//Arrays 类中的方法说明
void parallelPrefix(T[] array, BinaryOperator op)
作用:对数组中每个元素使用指定的二元操作函数进行替换操作,并行累积
参数 1:要替换的数组
参数 2:指定二元操作函数
案例步骤
案例代码
public class LambdaTest {
public static void main(String[] args) {
BinaryOperator operator = (m,n) -> m+n;
Integer [] arr = {2,1,3,5};
System.out.println("操作前的数组:" + Arrays.toString(arr)) ;
Arrays.parallelPrefix(arr,operator);
System.out.println("操作后的数组:" + Arrays.toString(arr)) ;
}
}
//输出结果
操作前的数组:[2, 1, 3, 5]
操作后的数组:[2, 3, 6, 11]
案例需求:
比较两个整数,使用 minBy 静态方法找出最小值比较两个字符串,使用 maxBy 静态方法找出最大值
案例步骤
案例代码
public class LambdaTest {
public static void main(String[] args) {
//naturalOrder()是 Comparator 中的静态方法,即按数字的正常大小进行比较
BinaryOperator oper1 = BinaryOperator.minBy(Comparator.naturalOrder());
System.out.println("最小值是:" + oper1.apply(3,5));
//naturalOrder()是 Comparator 中的静态方法,即按字符串的正常大小进行比较
BinaryOperator oper2 = BinaryOperator.maxBy(Comparator.naturalOrder());
System.out.println("最大值是:" + oper2.apply("ABCD","xyz"));
}
}
// 输出结果
最小值是:3
最大值是:xyz
UnaryOperator 表示对单个操作数的操作,该操作数生成与其操作数类型相同的结果。
UnaryOperator 接口继承于 Function 接口,
所以有 T apply(T t)抽象方法,与前面的 Function 接口中的 apply()方法相同。
它的输入类型和返回类型是相同的类型。
UnaryOperator 接口的源码
@FunctionalInterface
public interface UnaryOperator extends Function {
/**
* 始终返回其输入参数的一元运算符
*/
static UnaryOperator identity() {
return t -> t;
}
}
方法的演示
UnaryOperator 接口中的方法说明
T apply(T t);
从 Function 接口中继承下来的抽象方法,使用给定的参数应用此一元运算函数,返回另一个值。
参数和返回值是同一种类型。
static UnaryOperator identity()
始终返回其输入参数的一元运算符也就是后续 apply()输入的是什么,就返回什么。
案例步骤
public class LambdaTest {
public static void main(String[] args) {
//创建一个 UnaryOperator对象,
UnaryOperator operator = UnaryOperator.identity();
//调用 apply()方法,输出参数的值
System.out.println("输出与输入一样:" + operator.apply("abc"));
}
}
//输出结果
输出与输入一样:abc
案例需求:
有一个整数的列表集合,将集合中每个元素乘以 2,再替换这个元素,输出替换前后的列表集合有一个字符串的列表集合,将集合中每个元素用它的大写进行替换。
ArrayList 中的方法说明
replaceAll(UnaryOperator operator)
使用一元操作函数的结果,替换列表中的每个元素
案例步骤:
public class LambdaTest {
public static void main(String[] args) {
List nums = Arrays.asList(3, 10, 8, 2);
System.out.println("替换前:" + nums);
UnaryOperator oper = x -> x * 2;
nums.replaceAll(oper);
System.out.println("替换后:" + nums);
List names = Arrays.asList("Jack","Rose","Tom","NewBoy");
System.out.println("替换前:" + names);
names.replaceAll(s -> s.toUpperCase());
System.out.println("替换后:" + names);
}
}
//输出
替换前:[3, 10, 8, 2]
替换后:[6, 20, 16, 4]
替换前:[Jack, Rose, Tom, NewBoy]
替换后:[JACK, ROSE, TOM, NEWBOY]
(1)Supplier 提供数据者
- T get();没有传入参数,有结果。
(2)Consumer 消费数据者
- void accept(T t); 传入数据,没有结果。
- andThen()
(3)Predicate 谓语
- boolean test(T t); 对传入的数据逻辑判断
- and()
- or()
- negate()
- isEqual()
(4)Function 函数
- R apply(T t); 传入一个变量返回计算结果
- andThen()
- compose()
- identity()
(5)BinaryOperator 二元操作符
- T apply(T t,T u); 传入两个参数返回一个结果
- andThen()
- 继承于 BiFunction
(6)UnaryOperator
- 继承于 Function
- 一元操作符
- T apply(T t); 传入一个参数返回一个结果
- andThen()
- compose()
- identity()
参考:
Java 8 函数式接口
https://www.runoob.com/java/java8-functional-interfaces.html
死磕函数式接口——常用函数式接口
https://blog.csdn.net/heihaozi/article/details/104257942?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.control&spm=1001.2101.3001.4242
常用函数式接口
https://blog.csdn.net/h294590501/article/details/80303693