JAVA8新特性- 函数式接口

函数式接口定义

a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract

If an interface declares an abstract method overriding one of the public methods of 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 java.lang.Object or elsewhere.

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

函数式接口的概念(Functional Interface)就是只包含一个抽象方法的接口。 这类接口可以使用 lambda表达式方法引用构造函数引用

如果这个接口定义的抽象方法覆盖了 Object类的某个public方法,这个抽象方法不会被统计为抽象方法。

前面提到JAVA8以后接口支持默认方法,默认方法并非是抽象方法(有方法体),所以不会影响lambda表达式使用。

java8 中还提供刻一个注解 @FunctionalInterface, 该注解就是标识接口是函数式接口。使用该注解是一种语法规范,约束该接口只有一个抽象方法,如果该类存在多个抽象方法,编译器会立刻抛出错误提示。 但是不代表不使用该注解的接口就一定标记为非函数式接口

内置的函数式接口

java8中提供了,默认方法。但是如果只存在一个抽象方法,它依旧属于函数型接口。 在包 java.util.function 下提供了很多内置的函数式接口。

在这里插入图片描述

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;
    }
}

可以看到抽象方法是 apply, 其他方法是默认方法,静态方法(存在方法体)。 同时使用了@FunctionalInterface

apply

通常我们用到的就是apply方法,这是一个抽象方法,通过重写该方法实现自定义的逻辑。

		// 匿名内部类的方法创建 Function的对象
        Function<String,Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.valueOf(s);
            }
        };
		//调用
        System.out.println(function.apply("1234"));

上面提到了函数式接口可以使用 lambda表达式,简化后

Function<String,Integer> function = s -> Integer.valueOf(s);

使用lambda 方法引用。

Function<String, Integer> function = Integer::valueOf;


Optional 类中,存在一个实例方法map, 可以将结果转化。就用到了Function, 接收一个入参,一个返回值。

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }

示例: 将字符串转化为 整数类型

        Optional<String> stringOptional = Optional.of("12");
        Optional<Integer> integerOptional = stringOptional.map(Integer::valueOf);
        System.out.println(integerOptional.get());
andThen

可能会存在某种场景, 我们需要对操作的结果 做进一步的处理。

        Function<String, Integer> function = s -> Integer.valueOf(s);;
		// 字符串 转为数字类型后,我需要加10
        Function andThenFunction  = function.andThen(new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer + 10;
            }
        });
		// 当然了,还可以继续, 做其他处理
		
        System.out.println(andThenFunction.apply("10"));

输出结果:

20



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

这个是一个默认方法。

根据上面的例子,我们在代码中创建了两个Function实例。 再看定义, 内部又创建了一个新的Function实例。

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        return  new Function<T, V>() {
            @Override
            public V apply(T t) {
                return  after.apply(apply(t));;
            }
        };
    }

里面的处理逻辑,先执行调用andThen的Function,apply返回值作为入参 传递到 after.apply中, after的返回值作为最终结果。



compose 函数功能类似,区别在于。这个是compose传入的函数,在 apply 之前执行。

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
identity
 /**
  * Returns a function that always returns its input argument.
  *
  * @param <T> the type of the input and output objects to the function
  * @return a function that always returns its input argument
  */
 static <T> Function<T, T> identity() {
        return t -> t;
    }

首先是一个静态方法, 其次 内部是一个lambda表达式。 第一次看源码的时候,特别懵逼,鬼知道这是什么意思。

我们不妨看一下注释, 返回一个函数,这个函数的返回值始终为传入参数。 上面我们也看到了apply的lambda 表达式的简化写法。

与下面的写法等价

    static <T> Function<T, T> identity() {
        return new Function<T, T>() {
            @Override
            public T apply(T t) {
                return t;
            }
        };
    }
BiFunction

BiFunction 与Function 功能类似,区别就是有两个入参。

@FunctionalInterface
public interface BiFunction<T, U, R> {

    R apply(T t, U u);

  
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}
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); };
    }
}

抽象方法 accept, 一个入参无返回值。

accept
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("Hello World");

输出结果:

Hello World

lambda表达式:

    Consumer<String> consumer = s -> System.out.println(s);

方法引用:

   Consumer<String> consumer = System.out::println;


在接口List中存在元素遍历的方法,【forEach】。 它接收的参数就是 Consumer。

核心代码如下:

    public void forEach(Consumer<? super E> action) {
		// 获取 List中的元素
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; i < size; i++) {
        	// 遍历
            action.accept(elementData[i]);
        }
    }

比如要遍历集合的元素, 比较简单的写法:

    List<Integer> list = new ArrayList();
    list.forEach(System.out::println);
BiConsumer

接收两个入参:

@FunctionalInterface
public interface BiConsumer<T, U> {

    void accept(T t, U u);

    default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
        Objects.requireNonNull(after);

        return (l, r) -> {
            accept(l, r);
            after.accept(l, r);
        };
    }
}
Supplier
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

Supplier 属于 内置的函数式接口比较好理解的。 无参,有个返回值。

Optional 类中存在实例方法,用于返回默认值。

    public T orElse(T other) {
        return value != null ? value : other;
    }

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

orElseGet 方法就用到了 Supplier接口。

        Optional<List> optional = Optional.ofNullable(null);
        List list = optional.orElseGet(() -> new ArrayList());
        System.out.println(list);

返回结果:

[]

Predicate

Predicate 中的方法比较多,and、or、notEqual

@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 的 默认方法因为没有各种嵌套,所以看起来就直观很多。

比如 Optionnal中的filter 方法就使用到了 Predicate

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }
        Optional<String> strOptional = Optional.of("12");
        boolean isPresent = strOptional.filter(StringUtils::isEmpty).isPresent();
        System.out.println(isPresent);

false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值