函数式接口

函数式接口

概述

函数式接口在Java中是指:有且仅有一个抽象方法的接口。
函数式接口的实现可以由Lambda表达式、方法引用、构造器引用等方式实现。

前言

其实在1.8版本之前就已经出现了函数式接口了,例如:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener

@FunctionalInterface注解

为了对我们所编写的函数式接口进行校验,在Java8版本中引入了@FunctionalInterface,用来检验我们所编写的接口是否有且只有一个抽象方法,我们来看一个小栗子:

@FunctionalInterface
public interface MyFunctionalInterface(){
	void method();
}

我们写好了我们的接口那么下面我们来使用它吧

public class TestMyFunctionalInterface {

	public static void main(String[] args) {
		doSomething(()-> System.out.println("我被执行啦"));
	}

	private static void doSomething(MyFunctionalInterface inter){
		inter.method();
	}
}

如果我们在其中在增加一个抽象方法,那么我们的idea就会友善的给你进行飘红,当容你也不能没有抽象方法,必须是要有一个的。
那么就可能有小伙伴们有疑问了,Comparator<T>接口里面就有两个抽象方法呀,不信你看

@FunctionalInterface
public interface Comparator<T> {
	int compare(T o1, T o2);
	boolean equals(Object obj);

让我们来看看官方文档怎么说的:
\qquad If an interface declares an abstract method overriding one of the public methods of {@code java.lang.Object}, that also does not count toward the interface’s abstract method count since any implementation of the interface will have an implementation from {@code java.lang.Object} or elsewhere.
翻译过来就是:
如果接口中声明的抽象方法覆盖了java.lang.Object的公共方法,则该方法不会计入接口的抽象方法计数,因为该接口的任何实现都将具有java.lang.Object或其他地方的实现。

接口分类

在java.util.function包下面增加了很多函数式接口,一共有43种大体上可以被分为4种供给型、消费型、功能型、判断型

供给型接口

特点

无参,有返回值

接口
接口名抽象方法描述
SupplierT get()返回一个对象
BooleanSupplierboolean getAsBoolean()返回一个boolean值
DoubleSupplierdouble getAsDouble()返回一个double值
IntSupplierint getAsInt()返回一个int值
LongSupplierlong getAsLong()返回一个long值
代表 - Supplier接口

java.util.function.Supplier<T>对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据, 我们来看一个小栗子:

public class TestSupplier {

	public static void main(String[] args) {
		String strA = "Hello ";
		String strB = "World";
		String result = getString(() -> strA + strB);
		System.out.println(result);
	}

	static String getString(Supplier<String> supplier) {
		return supplier.get();
	}
}

消费型接口

特点

有参、无返回值

接口
接口名抽象方法描述
Consumervoid accept(T t)接收一个对象用于完成功能
BiConsumer<T,U>void accept(T t, U u)接收两个对象用于完成功能
DoubleConsumervoid accept(double value)接收一个double值
IntConsumervoid accept(int value)接收一个int值
LongConsumervoid accept(long value)接收一个long值
ObjDoubleConsumervoid accept(T t, double value)接收一个对象和一个double值
ObjIntConsumervoid accept(T t, int value)接收一个对象和一个int值
ObjLongConsumervoid accept(T t, long value)接收一个对象和一个long值
代表 - Consumer接口

java.util.function.Consumer<T>接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。我们来看个小栗子

public class TestConsumer {

	public static void main(String[] args) {
        consume(System.out::println);
	}

	public static void consume(Consumer<String> function){
		function.accept("Hello");
	}
}
默认方法 - andThen

如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作, 然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。下面是JDK的源代码:

default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }

我们来看一个小栗子

public class TestConsumer2 {

	public static void main(String[] args) {
		consume(c1 -> System.out.println(c1.toLowerCase()), 
				c2 -> System.out.println(c2.toUpperCase()));
	}

	public static void consume(Consumer<String> c1, Consumer<String> c2){
	c1.andThen(c2).accept("Hello");
}
}

判断型接口

特点

有参、返回值类型是boolean

接口
接口名抽象方法描述
Predicateboolean test(T t)接收一个对象
BiPredicate<T,U>boolean test(T t, U u)接收两个对象
DoublePredicateboolean test(double value)接收一个double值
IntPredicateboolean test(int value)接收一个int值
LongPredicateboolean test(long value)接收一个long值
代表 - Predicate

有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用 java.util.function.Predicate<T> 接口,我们看一个简单的小栗子

public class TestPredicate {

    public static void main(String[] args) {
        Boolean predicate = predicate(String::isEmpty);
        System.out.println("字符串是否为空:" + predicate);
    }

    private static Boolean predicate(Predicate<String> p){
        return p.test("");
    }
}
默认方法 - and

其中将两个 Predicate 条件使用“与”逻辑连接起来实现“并且”的效果时,可以使用default方法 and 。其JDK源码为:

default Predicate<T> and(Predicate<? super T> other) {
	Objects.requireNonNull(other);
	return (t) -> test(t) && other.test(t);
}
默认方法 - negate

实现“非”(取反)非常简单。默认方法 negate 的JDK源代码为:

default Predicate<T> negate() {
	return (t) -> !test(t);
}
默认方法 - or

与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”。JDK源码为:

default Predicate<T> or(Predicate<? super T> other) {
	Objects.requireNonNull(other);
	return (t) -> test(t) || other.test(t);
}

功能型接口

特点

有参数、有返回值

接口
接口名抽象方法描述
Function<T,R>R apply(T t)接收一个T类型对象,返回一个R类型对象结果
UnaryOperatorT apply(T t)接收一个T类型对象,返回一个T类型对象结果
DoubleFunctionR apply(double value)接收一个double值,返回一个R类型对象
IntFunctionR apply(int value)接收一个int值,返回一个R类型对象
LongFunctionR apply(long value)接收一个long值,返回一个R类型对象
ToDoubleFunctiondouble applyAsDouble(T value)接收一个T类型对象,返回一个double
ToIntFunctionint applyAsInt(T value)接收一个T类型对象,返回一个int值
ToLongFunctionlong applyAsLong(T value)接收一个T类型对象,返回一个long值
DoubleToIntFunctionint applyAsInt(double value)接收一个double值,返回一个int值
DoubleToLongFunctionlong applyAsLong(double value)接收一个double值,返回一个long值
IntToDoubleFunctiondouble applyAsDouble(int value)接收一个int值,返回一个double值
IntToLongFunctionlong applyAsLong(int value)接收一个int值,返回一个long值
LongToDoubleFunctiondouble applyAsDouble(long value)接收一个long值,返回一个double值
LongToIntFunctionint applyAsInt(long value)接收一个long值,返回一个int值
DoubleUnaryOperatordouble applyAsDouble(double operand)接收一个double值,返回一个double值
IntUnaryOperatorint applyAsInt(int operand)接收一个int值,返回一个int值
LongUnaryOperatorlong applyAsLong(long operand)接收一个long值,返回一个long值
BiFunction<T,U,R>R apply(T t, U u)接收一个T类型和一个U类型对象,返回一个R类型对象
BinaryOperatorT apply(T t, T u)接收两个T类型对象,返回一个T类型对象
ToDoubleBiFunction<T,U>double applyAsDouble(T t, U u)接收一个T类型和一个U类型对象,返回一个double值
ToIntBiFunction<T,U>int applyAsInt(T t, U u)接收一个T类型和一个U类型对象,返回一个int值
ToLongBiFunction<T,U>long applyAsLong(T t, U u)接收一个T类型和一个U类型对象,返回一个long值
DoubleBinaryOperatordouble applyAsDouble(double left, double right)接收两个double值,返回一个double值
IntBinaryOperatorint applyAsInt(int left, int right)接收两个int值,返回一个int值
LongBinaryOperatorlong applyAsLong(long left, long right)接收两个long值,返回一个long值
代表 - Function

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。我们来看一个小栗子:

public class TestFunction {
    public static void main(String[] args) {
        Integer function = function(Integer::valueOf);
        System.out.println(function + 3);
    }

    public static Integer function(Function<String, Integer> f){
        return f.apply("123");
    }
}
默认方法 - compose

compose方法接收一个Function类型的参数,先用传入的Function对象执行对应的apply方法,然后使用当前的Function对象的执行对应的apply方法

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
	Objects.requireNonNull(before);
	return (V v) -> apply(before.apply(v));
}
默认方法 - andThen

Function 接口中有一个默认的 andThen 方法,用来进行组合操作。JDK源代码如:

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
	Objects.requireNonNull(after);
	return (T t) -> after.apply(apply(t));
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值