Java8新特性学习-函数式接口

Java8新特性学习😝

Java大家庭已经出到11版本了,我还在使用jdk7=-=,再不学就来不及了,所以赶紧学一下Java8的新特性。


介绍

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口

函数式接口在java.util.function路径下。

在这个包中,每一个接口都被@FunctionalInterface标注,表示这个类是一个函数式接口,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。– 摘录自菜鸟编程


具体使用

这次我们简单粗暴一下,贴出测试代码,看下具体使用场景和用法吧

在每个方法中都写上了注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package com.example.demo;

import com.example.demo.test.Car;
import com.example.demo.test.PrintConsumer;
import org.junit.Test;

import java.util.Comparator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.DoubleToIntFunction;
import java.util.function.Function;

/**
* @author JingQ at 2019/1/25
*/
public class JDK8FunctionInterfaceTest {

/**
* BiConsumer<T, U>,接收两个参数,不返回结果(void)
*
* 输出:(说明函数内修改对象引用的话同时会修改对象的值)
* 娃哈哈真好喝
* TEST
*/
@Test
public void biConsumerTest() {
BiConsumer<Car, String> biConsumer = (a, b) -> {
System.out.println(a.getName() + b);
a.setName("TEST");
};
Car car = new Car();
car.setName("娃哈哈");
biConsumer.accept(car, "真好喝");
System.out.println(car.getName());
}

/**
* BiFunction<T, U, R>, 接收两个参数<T, U>,返回R类型的结果
* 输出:
* 0 - 相等
*/
@Test
public void biFunctionTest() {
BiFunction<Integer, Integer, String> biFunction = (a, b) -> String.valueOf(a+b);
System.out.println(biFunction.apply(1, 2).compareTo("3"));
}

/**
* BinaryOperator<T> 用来接收两个T类型的参数,返回T类型的结果
*/
@Test
public void binaryOperatorTest() {
// 比较两者的最大值
BinaryOperator<Integer> binaryOperator1 = BinaryOperator.maxBy(Comparator.naturalOrder());
System.out.println(binaryOperator1.apply(1, 2));

// 比较两者的最小值
BinaryOperator<Integer> binaryOperator2 = BinaryOperator.minBy(Comparator.naturalOrder());
System.out.println(binaryOperator2.apply(3, 4));

// 相加
BinaryOperator<Integer> add = (n1, n2) -> n1 + n2;
System.out.println(add.apply(1, 3));
}

/**
* BiPredicate<T, U>,接收两个参数<T, U>,返回一个boolean类型结果
* 输出:
* false
*/
@Test
public void biPredicateTest() {
BiPredicate<Integer, Integer> biPredicate = (a, b) -> a.equals(b);
System.out.println(biPredicate.test(1, 3));
}

/**
* Boolean类型 提供者,用来获取一个Boolean值
* 如果只是用来返回true/false,感觉这个方法比较鸡肋;感觉可以使用statement,在返回结果前执行
*/
@Test
public void booleanSupplierTest() {
BooleanSupplier booleanSupplier = () -> {
System.out.println("Pre Action");
return Boolean.TRUE;
};
System.out.println(booleanSupplier.getAsBoolean());
}

/**
* Consumer<T>,接受一个输入参数,返回空类型void
* 还有一个andThen,可以用来实现责任链模式
*
* 输出:
* TEST
*
* NEXT TEST
* Pre
* End
*/
@Test
public void consumerTest() {
// 接受String类型的参数
Consumer<String> consumer = System.out::println;
consumer.accept("TEST");
//空格预定
System.out.println();
// 责任链模式,可以设定下一个consumer
// PrintConsumer.java
// public void accept(String s) {
// System.out.println("Pre");
// //xxx
// System.out.println("End");
// }
Consumer<String> nextConsumer = new PrintConsumer();
consumer.andThen(nextConsumer).accept("NEXT TEST");
}

/**
* DoubleToIntFunction 只有一个applyAsInt方法,接受double类型的参数,返回int类型的结果
*/
@Test
public void doubleToIntFunctionTest() {
DoubleToIntFunction doubleToIntFunction = a -> (int) a;
System.out.println(doubleToIntFunction.applyAsInt(10L));
}

/**
* Function<T, U>函数接口,接受T类型的参数,返回U类型的结果
*
* compose和andThen这两个方法的区别在于执行方法的顺序问题
*
* compose先执行后面函数,然后执行前面的函数;andThen先执行前面的函数,然后再执行后面的函数
*/
@Test
public void functionTest() {
// 方法引用,Integer[类名]::valueOf[方法名](这个是静态方法引用)
Function<String, Integer> function1 = Integer::valueOf;
System.out.println(function1.apply("1010"));
// 输出 1010

// andThen方法的入参类型为上一个方法的返回类型
Function<Integer, String> function2 = a -> {
System.out.println("Pre Action : ");
return String.valueOf(a) + "10";
};
System.out.println(function1.andThen(function2).apply("1010"));
//输出
//Pre Action :
//101010

// compose方法
Function<Integer, String> function3 = a -> {
System.out.println(a);
return a + "2020";
};
//compose先执行后面函数, 需要注意参数传递时调用的方法是否兼容,避免报错
System.out.println(function1.compose(function3).apply(10));
//输出
//10
//102020
}

}

小结

其它类型例如DoubleToLongFunction、IntSupplier之类的函数式接口,就是转换一下入参类型和出参类型,在用的时候查一下包下的API就能了解~


参考资料

  1. Java 8 函数式接口