Java8新特性_四大函数式接口

187 阅读3分钟

前言

​ lambda表达式是Java JDK8的新特性,可以避免定义多过的匿名内部类,写出更优雅的Java代码。但是它有一个前提,调用的接口必须是函数式接口,要求接口里只有一个待实现的抽象方法,通常会在接口头部写上注解@FunctionalInterface。

// 接口定义
@FunctionalInterface
interface MyFunctional {
    void do(String str);
}

// 接口使用
MyFunctional functional = str -> System.out.println(str);
functional.do("something");

lambda表达式介绍 >

一、Consumer(消费型)

​ 接收一个类型T的参数,没有返回值。

源码介绍

@FunctionalInterface
public interface Consumer<T> {
	/**
	 * 接收一个类型T的参数,没有返回值。
	 */
    void accept(T t);

    /**
     * 相当于链式操作,对给定的参数进行多次操作。
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

代码示例

public static void main(String[] args)  {
    // 方法一:普通方法
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("hello world");

        // 方法二:lambda表达式
        Consumer<String> consumer2 = str-> System.out.println(str);
        consumer2.accept("gogogo");

        // andThen 方法
        consumer.andThen(consumer2).accept("xiaoming");
}

二、Supplier(供给型)

​ 不接受任何参数,返回类型T的结果。

源码介绍

@FunctionalInterface
public interface Supplier<T> {
	/**
	 * 不接受任何参数,返回类型T的结果。
	 */
    T get();
}

代码示例

public static void main(String[] args) {
    // 方法一:普通方法
    Supplier<String> supplier = new Supplier() {
        @Override
        public String get() {
            return "hello world";
        }
    };
    System.out.println(supplier.get());

    // 方法二:lambda表达式
    Supplier<String> supplier2 = () -> "hello world";
    System.out.println(supplier2.get());
}

三、Function(函数型)

​ 接收一个类型T参数,返回一个类型R的结果。

源码介绍

@FunctionalInterface
public interface Function<T, R> {
	/**
	 * 接收一个类型T参数,返回一个类型R的结果。
	 */
    R apply(T t);

    /**
     * 相当于链式操作,先将给定的参数传入before进行操作,操作结果再使用外层函数进行操作。
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * 相当于链式操作,先将给定的参数传入外层函数进行操作,操作结果再使用after进行操作。
     */
    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;
    }
}

代码示例

public static void main(String[] args) {
    // 方法一:普通方法
    Function<Integer, Integer> function = new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer i) {
            return i + i;
        }
    };
    System.out.println(function.apply(2));

    // 方法二:lambda表达式
    Function<Integer, Integer> function2 = (i) -> i * i;
    System.out.println(function2.apply(3));

    // compose 方法
    System.out.println(function.compose(function2).apply(4));

    // andThen 方法
    System.out.println(function.andThen(function2).apply(4));

    // identity 方法 相当于 this -> this
    Arrays.asList("a", "b", "c").stream()
        .map(Function.identity()) // <- This,
        .map(str -> str)          // <- is the same as this.
        .collect(Collectors.toMap(
            Function.identity(), // <-- And this,
            str -> str));        // <-- is the same as this.
}

四、Predicate(断言型)

​ 接收一个类型T的参数,给出判断结果。

源码介绍

@FunctionalInterface
public interface Predicate<T> {
	/**
	 * 接收一个类型T的参数,给出判断结果。
	 */
    boolean test(T t);

    /**
     * 先使用外层方法判断,再使用other方法判断,理解为:this&&other
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    
	/**
     * 先使用外层方法判断,将结果值进行取反,理解为:!this
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * 先使用外层方法判断,再使用other方法判断,理解为:this||other
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * 使用外层方法判断,再和other方法结果进行比较,理解为:this==other
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

代码示例

public static void main(String[] args) {
    // 方法一:普通方法
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.isEmpty();
            }
        };
        System.out.println(predicate.test("1024"));

        // 方法二:lambda表达式
        Predicate<String> predicate2 = (str) -> str.isEmpty();
        System.out.println(predicate2.test(""));

        // and 方法
        System.out.println(predicate.and(predicate2).test("1024"));

        // or 方法
        System.out.println(predicate.or(predicate2).test("1024"));

        // negate 方法
        System.out.println(predicate.negate().test("1024"));

        // isEqual 方法
        System.out.println(Predicate.isEqual("1024"));
}

五、总结

整理:

函数式接口参数类型返回类型用途
ConsumerTvoid接收一个类型T的参数,没有返回值。
SupplierT不接受任何参数,返回类型T的结果。
Function<T,R>TR接收一个类型T参数,返回一个类型R的结果。
PredicateTboolean接收一个类型T的参数,给出判断结果.

作用:

  1. 函数式接口里有默认方法和静态方法,不需要重写即可使用。
  2. 结合Java的面向对象编程思想,函数式接口就是将方法当做“对象”进行传输。
  3. 在Java jdk8 新特性stream流中,函数式接口被大量使用。