Function<T,R> 接口,内置的函数接口,其接受两个参数,一个入参T,一个出参R

拼接字符串

举例:假如一个方法是用来拼接字符串的,需要的入参是String类型的,出参也是String类型的。
非java8时你可能会这样写:

1
2
3
4
5
6
public String appendStr(String oriStr, String appendStr) {
return oriStr + appendStr;
}

//使用;
String result = appendStr("hello", " world !");

从上面可以明确的看出 它的入参和出参都是String,用Function就可以这样写:

1
2
3
4
5
6
public String appendStr(String oriStr, Function<String, String> strFunction) {
return strFunction.apply(oriStr);
}

// 使用:
String result = appendStr("hello", (x) -> x + " world !");

上面举了一个比较简单的例子,便于理解Function接口的使用。

元素是否存在

举例:查找某一个元素是否在列表中存在

非java8 时你可能会这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static <T> boolean isExist(Collection<T> list, T t) {
if (CollectionUtils.isEmpty(list)) {
return false;
}

for (T t1 : list) {
if (t1.equals(t)) {
return true;
}
}

return false;
}

从上面可以看到,需要传入一个list,和要查询的目标值,这样判断逻辑都在其中,不利于扩展,其实我们只需要知道一个元素是否在这个元素是否在这个list中,在的话返回true,不在的话返回false, 所以我们可以把具体的操作抽象为一个返回值为Boolean的接口,具体的实现由具体的实现类去实现或内部类去实现。

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
// 定义一个接口
@FunctionalInterface
interface Predicate<T> {
boolean test(T t);
}
// @FunctionalInterface 表名它是一个函数式接口,确保该接口只有一个抽象方法。

public static <T> boolean exist(Collection<T> list, Predicate match) {
if (CollectionUtils.isEmpty(list)) {
return false;
}
for (T t : list) {
if (match.test(t)) {
return true;
}
}
return false;
}

// 调用
List<String> list = Arrays.asList(10, 20, 30, 40);
boolean result1 = exist(list, (x) -> x.equals(30));
//或者
boolean result2 = exist(list, new Predicate() {
@Override
public boolean test(Object o) {
// 这里的o相当于list遍历时的每个元素
return o.equals(30);
}
});

上面我们已经将判断的部分抽象为了接口,将判断的逻辑放在了传参出,内部只需要知道你的结果是true还是false就足够了,可以看到这个接口需要一个入参为T,返回参数为Boolean,这时Function恰好可以满足,我们就不必自定义函数接口了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static <T> boolean isExist(Collection<T> list, Function<T, Boolean> function) {
if (CollectionUtils.isEmpty(list)) {
return false;
}

for (T t : list) {
if (function.apply(t)) {
return true;
}
}

return false;
}

// 调用:
List<Integer> oriList = Arrays.asList(10, 20, 30, 40);
boolean exist = isExist(oriList, x -> x.equals(30));

查找list中的某个元素,并返回此元素

举一反三,如何查询一个元素是否存在于某个list中呢?如果存在的话则返回这个元素

1
2
3
4
5
6
7
8
9
10
11
public static <T> T findData(Collection<T> list, Function<T, Boolean> function) {
if (CollectionUtils.isEmpty(list)) {
return null;
}
for (T t : list) {
if (function.apply(t)) {
return t;
}
}
return null;
}

总结:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
其实 match.test 调用的就是`Predicate`中的`test`方法, t为传给`Predicate`的参数
public static <T> boolean exist(Collection<T> list, Predicate match) {
//...
for (T t : list) {
if (match.test(t)) {
return true;
}
}
return false;
}

// 调用
List<String> list = Arrays.asList(10, 20, 30, 40);
boolean result1 = exist(list, (x) -> x.equals(30));
//或者
boolean result2 = exist(list, new Predicate() {
@Override
public boolean test(Object o) {
// 这里的o相当于list遍历时的每个元素
return o.equals(30);
}
});

Function<T,R> 函数式接口,T代表入参,R代表出参,当你的函数有出参和入参时都可使用此接口,当然java8还提供了许多类似的函数式接口来方便我们的使用,以后再来总结。