Java8 函数式编程学习--四大内置函数式接口

概述

Lambda表达式的使用前提是函数式接口,为了便利Lambda表达式的使用,Java8提供了内置的四大函数式接口,四大函数式接口满足了程序设计的大部分情况,省去了使用Lambda表达式时写函数式接口的步骤。
四大函数式接口分别为:ConsumerSupplierFunctionPredicate,参数及返回值类型如下表所示:

函数式接口 抽象方法 传入参数类型 返回值类型
Consumer accept T void
Supplier get T
Function apply T R
Predicate test T boolean

内容

Consumer

源码

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

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

}

分析

Consumer有函数式接口的注解“@FunctionalInterface”,说明Consumer需要满足函数式接口的要求,要求具体见初识函数式接口
Consumer顾名思义是一个消费者,用于消费T类型的对象,并没有产生返回值;

accept方法

抽象方法accept()没有返回值类型,用于处理T类型对象;

andThen方法

指定调用完当前Consumer方法后是否还需要调用其它Consumer的accept()方法的default方法andThen()。

示例代码

通过Consumer接口来处理Person类型的数据,分别输出Person的姓名和年龄。

public class ConsumerDemo {

	public static void main(String[] args) {
		Consumer<Person> con1 = (person) -> System.out.println(person.getName());
		Consumer<Person> con2 = (person) -> System.out.println(person.getAge());
		Person per = new Person("张三", 20);
		con1.accept(per);
		con1.andThen(con2).accept(per);
		con2.andThen(con1).accept(per);
	}
	
}

运行结果

张三
张三
20
20
张三

注意

调用andThen()方法的con2和con1处理的数据是同一个数据,都是通过accept()方法接收到的per,只是在处理方法上有所不同。

Supplier

源码

@FunctionalInterface
public interface Supplier<T> {
    
    T get();
    
}

分析

Supplier也满足函数式接口的定义,有“@FunctionalInterface”注解;
Supplier顾名思义是一个提供者,它不需要传入任何的参数,就可以获得提供一个T类型的对象;

get方法

Supplier仅有一个用于提供T类型对象的抽象方法get()。

示例代码

中国的年满18岁的程序员会分配到国家提供的女朋友。

public class SupplierDemo {
	public static void main(String[] args) {
		Supplier<Person> china = () -> new Person("girl", 18);
		Person programmer = new Person("程序员", 18);
		programmer.setFriend(china.get());
		System.out.println(programmer.toString());
	}
}

运行结果

我覆写了toString()方法,结果如下:
name: 程序员
age: 18
friend: girl

Function

源码

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

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

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

分析

Function满足函数式接口的定义,有“@FunctionalInterface”注解,它的具体方法如下:

apply方法

Function顾名思义是一个函数,经常被作为一个中间函数调用,所以有一个含有输入和输出的抽象方法apply(),apply()用于处理T类型的对象,返回R类型的结果;

andThen方法

Function有一个Consumer中也有的功能相同的默认方法andThen(),用于指定当前的Function的apply()方法执行完毕后是否需要执行的下一个Function。

compose方法

Function中compose()方法功能与andThen()类似。顺序不同,compose() 先执行参数,再执行调用者。

identity方法

Function的identity()是一个用于返回当前正在执行的方法的一个静态方法。

示例代码

public class FunctionDemo {
	public static void main(String[] args) {
		Function<Person, Person> dating = (s) -> { // 一个交友的方法
			s.setFriend(new Person("张三", 20));
			return s;
		};
		Function<Person, Person> breakUp = (s) -> { // 一个和朋友断交的方法
			s.setFriend(new Person("", 0));
			return s;
		};

		Person person = new Person("李四", 25);
		dating.apply(person); // 测试apply() -> 让李四和张三交朋友
		System.out.println(person.toString());

		System.out.println("-------------------------");
		person = new Person("李四", 25); // 初始化李四
		dating.andThen(breakUp).apply(person); // 测试andThen() -> 让李四先交朋友再断交
		System.out.println(person.toString());

		System.out.println("-------------------------");
		person = new Person("李四", 25); // 初始化李四
		dating.compose(breakUp).apply(person); // 测试andThen() -> 让李四先断交再交朋友
		System.out.println(person.toString());

		System.out.println("-------------------------");
		System.out.println(Function.identity().apply(person)); // 测试当前正在执行的方法
	}
}

运行结果

name:	李四
age:	25
friend:	张三
-------------------------
name:	李四
age:	25
friend:	
-------------------------
name:	李四
age:	25
friend:	张三
-------------------------
name:	李四
age:	25
friend:	张三

注意

  • Function中的四个方法,除了抽象方法apply(),其余都能返回一个Function类型的对象用于迭代;
  • andThen()和compose()功能相同,顺序相反。

Predicate

源码

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

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

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

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

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

分析

Predicate满足函数式接口的定义,有“@FunctionalInterface”注解,它的具体方法如下:

test方法

抽象方法test(),用于处理T类型的对象,并且返回一个布尔型的值表达处理的结果。

and方法

默认方法and(),与短路与“&&”运算符类似,传入一个Predicate对象,返回一个Predicate类型对象,用于连接两个Predicate类型的对象,连接后全真才为真。

or方法

默认方法or(),与短路运算符“||”类似,传入一个Predicate对象,返回一个Predicate类型对象,用于连接两个Predicate类型的对象,连接后有真即为真。

negate方法

默认方法negate(),与关系运算符“!”类似,没有传入参数,返回一个Predicate类型对象,用于取反操作。

isEqual方法

静态方法isEqual(),接收一个Object类型的对象,返回一个Predicate类型对象,用于判断第一个test的方法与第二个test方法是否相同。

示例代码

public class PredicateDemo {
	public static void main(String[] args) {
		Predicate<String> judge = (str) -> str.equals("皮一下就很开心");
		Predicate<String> p = (s) -> s.equals("皮");
		String str = "皮一下就很开心";
		System.out.println(judge.test(str));
		System.out.println(judge.negate().test(str));		//!true
		System.out.println(judge.and(p).test(str));			//false&&true
		System.out.println(judge.or(p).test(str));			//false||true
	}
}

运行结果

true
false
false
true

参考

Java8新特性学习-函数式编程
JAVA8之函数式编程Predicate接口

猜你喜欢

转载自blog.csdn.net/qq_39942013/article/details/89048048