我们看看跟函数式编程相关的接口
java.long.FunctionalInterface是一个注解接口,函数接口都会实现它,看看它有什么特别的
从这里我们可以看出来一个函数接口只有一个抽象方法,但是如果要加一切其他的功能怎么办呢?接口中添加功能的话相当麻烦,接口相关实现类都需要修改,接下来“default”就登场了
default方法只能在接口出现,它不是抽象方法,可以通过methodInstance.isDefault()辨认,咦,弄啥勒,接口还能有普通方法?是的你没看错,添加default方法是为了方便修改接口,不至于每次修改过后都要将他的“儿子,孙子”等实现一一修改;如果在接口中default修饰的方法不加body会怎么样呢? 没错, 会编译失败!贴图:
接口中的default方法不用强制在实现类中 出现,当然业务需要的话,也可以重写来进行多态;
下面是java.util.function中的函数接口描述
| 序号 | 接口 & 描述 |
| — | — |
| 1 | BiConsumer<T,U>
代表了一个接受两个输入参数的操作,并且不返回任何结果
|
| 2 | BiFunction<T,U,R>
代表了一个接受两个输入参数的方法,并且返回一个结果
|
| 3 | BinaryOperator
代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
|
| 4 | BiPredicate<T,U>
代表了一个两个参数的boolean值方法
|
| 5 | BooleanSupplier
代表了boolean值结果的提供方
|
| 6 | Consumer
代表了接受一个输入参数并且无返回的操作
|
| 7 | DoubleBinaryOperator
代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
|
| 8 | DoubleConsumer
代表一个接受double值参数的操作,并且不返回结果。
|
| 9 | DoubleFunction
代表接受一个double值参数的方法,并且返回结果
|
| 10 | DoublePredicate
代表一个拥有double值参数的boolean值方法
|
| 11 | DoubleSupplier
代表一个double值结构的提供方
|
| 12 | DoubleToIntFunction
接受一个double类型输入,返回一个int类型结果。
|
| 13 | DoubleToLongFunction
接受一个double类型输入,返回一个long类型结果
|
| 14 | DoubleUnaryOperator
接受一个参数同为类型double,返回值类型也为double 。
|
| 15 | Function<T,R>
接受一个输入参数,返回一个结果。
|
| 16 | IntBinaryOperator
接受两个参数同为类型int,返回值类型也为int 。
|
| 17 | IntConsumer
接受一个int类型的输入参数,无返回值 。
|
| 18 | IntFunction
接受一个int类型输入参数,返回一个结果 。
|
| 19 | IntPredicate
:接受一个int输入参数,返回一个布尔值的结果。
|
| 20 | IntSupplier
无参数,返回一个int类型结果。
|
| 21 | IntToDoubleFunction
接受一个int类型输入,返回一个double类型结果 。
|
| 22 | IntToLongFunction
接受一个int类型输入,返回一个long类型结果。
|
| 23 | IntUnaryOperator
接受一个参数同为类型int,返回值类型也为int 。
|
| 24 | LongBinaryOperator
接受两个参数同为类型long,返回值类型也为long。
|
| 25 | LongConsumer
接受一个long类型的输入参数,无返回值。
|
| 26 | LongFunction
接受一个long类型输入参数,返回一个结果。
|
| 27 | LongPredicate
R接受一个long输入参数,返回一个布尔值类型结果。
|
| 28 | LongSupplier
无参数,返回一个结果long类型的值。
|
| 29 | LongToDoubleFunction
接受一个long类型输入,返回一个double类型结果。
|
| 30 | LongToIntFunction
接受一个long类型输入,返回一个int类型结果。
|
| 31 | LongUnaryOperator
接受一个参数同为类型long,返回值类型也为long。
|
| 32 | ObjDoubleConsumer
接受一个object类型和一个double类型的输入参数,无返回值。
|
| 33 | ObjIntConsumer
接受一个object类型和一个int类型的输入参数,无返回值。
|
| 34 | ObjLongConsumer
接受一个object类型和一个long类型的输入参数,无返回值。
|
| 35 | Predicate
接受一个输入参数,返回一个布尔值结果。
|
| 36 | Supplier
无参数,返回一个结果。
|
| 37 | ToDoubleBiFunction<T,U>
接受两个输入参数,返回一个double类型结果
|
| 38 | ToDoubleFunction
接受一个输入参数,返回一个double类型结果
|
| 39 | ToIntBiFunction<T,U>
接受两个输入参数,返回一个int类型结果。
|
| 40 | ToIntFunction
接受一个输入参数,返回一个int类型结果。
|
| 41 | ToLongBiFunction<T,U>
接受两个输入参数,返回一个long类型结果。
|
| 42 | ToLongFunction
接受一个输入参数,返回一个long类型结果。
|
| 43 | UnaryOperator
接受一个参数为类型T,返回值类型也为T。
|
除了上面列出的,还有个别函数接口没列出来,例如Comparator(), 但总归是个函数接口都会基于FunctionalInterface注解
总结
这些函数主要还是分为几个主要函数,其余都是以其为基础的分化;
-
Supplier 无参数,返回一个结果。
-
Consumer 代表了接受一个输入参数并且无返回的操作。
-
Function<T,R> 接受一个输入参数,返回一个结果,返回的结果跟参数的类型无关。
-
Predicate 接受一个输入参数,返回一个布尔值结果。
-
BinaryOperator 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果,xxxOperator 函数都是接受类型跟返回值类型相同。
而且,从上面五个主要函数接口命名也可以看出其作用,"Bi"作为前缀的都是属于二元操作,接受两个参数。
T1to_T2_是从接受T1类型参数,返回T2类型结果,比如IntToLongFunction 接受一个int类型参数,返回long类型结果。
实战1
下面我写了一个功能,拳击手有分组跟体重两个属性,然后给一组拳击手集合,根据小组或者体重级排序,用到的是Comparator(),也是一个函数接口
上码:
-
/**
-
* Created by zhanghe
-
* 拳击手
-
*/
-
public class Boxer {
-
//分组
-
private String group;
-
//重量级
-
private Integer weight;
-
public Boxer(String group, Integer weight) {
-
this.group = group;
-
this.weight = weight;
-
}
-
public static <T> List<List<T>> divider(List<T> datas, Comparator<T> c) {
-
//声明一个列表来接收各个分组
-
List<List<T>> list = new ArrayList<>();
-
for (T t : datas) {
-
//通过isSameGroup 标识来判断分组是否已创建
-
boolean isSameGroup = false;
-
for (int i = 0; i < list.size(); i++) {
-
//compare函数返回值为int,正数说明param1>param2,0说明param1=param2,负数说明param1<param2
-
//这里用到的原理是将List列表datas中的各项与分组列表list中的元素比较(比较的规则由外面作为参数传递,这就是函数式编程),
-
// 值为0表示规则相符即为同一组
-
if (c.compare(t, list.get(i).get(0)) == 0) {
-
isSameGroup = true;
-
list.get(i).add(t);
-
break;
-
}
-
}
-
//比较完了发现没有规则相符的,即自成一系
-
if (!isSameGroup) {
-
List<T> e = new ArrayList<>();
-
e.add(t);
-
list.add(e);
-
}
-
}
-
return list;
-
}
-
public static void main(String[] args) {
-
List<Boxer> boxers = Arrays.asList(
-
new Boxer("红队", 120),
-
new Boxer("绿队", 180),
-
new Boxer("蓝队", 200),
-
new Boxer("绿队", 220),
-
new Boxer("蓝队", 120),
-
new Boxer("红队", 80),
-
new Boxer("红队", 90),
-
new Boxer("绿队", 240)
-
);
-
List<List<Boxer>> dividByGroup = divider(boxers, new Comparator<Boxer>() {
-
@Override
-
public int compare(Boxer o1, Boxer o2) {
-
//分组一样 即认为 相同
-
return o1.group.equals(o2.group) == true ? 0 : 1;
-
}
最后
给大家送一个小福利
附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。
-
new Boxer("红队", 120),
-
new Boxer("绿队", 180),
-
new Boxer("蓝队", 200),
-
new Boxer("绿队", 220),
-
new Boxer("蓝队", 120),
-
new Boxer("红队", 80),
-
new Boxer("红队", 90),
-
new Boxer("绿队", 240)
-
);
-
List<List<Boxer>> dividByGroup = divider(boxers, new Comparator<Boxer>() {
-
@Override
-
public int compare(Boxer o1, Boxer o2) {
-
//分组一样 即认为 相同
-
return o1.group.equals(o2.group) == true ? 0 : 1;
-
}
最后
给大家送一个小福利
[外链图片转存中…(img-WQyOMJ2x-1721136883040)]
附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。
[外链图片转存中…(img-6d90Y2nN-1721136883041)]