Java Miscellaneous Series-Functional Interface (java.util.function package)

Other URL

JDK8 function interface Function, Consumer, Predicate, Supplier_ Jiurou ape -CSDN blog
Java8 Detailed interface function in Function and use _Life is for sharing the blog -CSDN blog
JAVA8 explain the java.util.function package (conveniently a function of the formula Programming)_I am guyue, guyue is me O(∩_∩)O-CSDN Blog

"Java Development Actual Combat Classic 2nd Edition" => 16.10 Built-in functional interface

Introduction

JDK1.8 function interface changes

New function interface added in JDK1.8:

  • java.util.function
  • java.util.stream

Functional interfaces that existed before JDK 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

Common interface

Interface definition

Description

effect

Function< T, R >

Functional interface

Receive the T object and return the R object.

Consumer< T >

Consumer interface

Receive T object, no return value

Supplier< T >

Supply interface

Do not receive value, return T object

Predicate< T >

Assertion interface

Receive T object and return boolean

Uncommon interface

Interface definition

description

UnaryOperator< T >

Receive T object, return T object

BiConsumer<T, U>

Receive T object and U object, do not return value

BiPredicate<T, U>

Receive T object and U object, return boolean

BiFunction<T, U, R>

Receive T object and U object, return R object

BinaryOperator< T >

Receive two T objects and return T objects

Function< T, R> Function type

Introduction

Overview

effect

Realize a "unary function", that is, pass in a value and return another value through the calculation of the function.

scenes to be used

V HashMap.computeIfAbsent(K, Function<K, V>) // Simplify the code. If the specified key is not yet associated with a value or is associated with null, replace it with the return value of the function.
<R> Stream<R> map(Function<? super T,? Extends R> mapper); // convert stream

Design ideas

The idea of ​​unary function extracts the conversion logic and decouples

definition

package java.util.function;
import java.util.Objects;

@FunctionalInterface
public interface Function<T, R> {
    // 接受输入参数,对输入执行所需操作后  返回一个结果。
    R apply(T t);

    // 返回一个 先执行before函数对象apply方法,再执行当前函数对象apply方法的 函数对象。
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
       Objects.requireNonNull(before);
       return (V v) -> apply(before.apply(v));
    }

    // 返回一个 先执行当前函数对象apply方法, 再执行after函数对象apply方法的 函数对象。
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }   

    // 返回一个执行了apply()方法之后只会返回输入参数的函数对象。
    static <T> Function<T, T> identity() {
        return t -> t;
    } 
}

All interfaces

Interface definition

description

Function< T, R >

Receive the T object and return the R object.

DoubleFunction<R>

A function that receives a double parameter and returns the result

DoubleToIntFunction

A function that receives a double parameter and returns an int result

DoubleToLongFunction

A function that receives a double parameter and returns a long result

IntFunction<R>

A function that receives a parameter of type int and returns the result

IntToDoubleFunction

A function that receives an int type parameter and returns a double result

IntToLongFunction

A function that receives a parameter of type int and returns a long result

LongFunction<R>

A function that receives a long parameter and returns the result

LongToDoubleFunction

A function that receives a long parameter and returns a double result

LongToIntFunction

A function that receives a long parameter and returns an int result

ToDoubleBiFunction<T,U>

A function that takes two parameters and returns a double result

ToDoubleFunction<T>

A function that takes a parameter and returns a double result

ToIntBiFunction<T,U>

A function that receives two parameters and returns an int result

ToIntFunction<T>

A function that receives a parameter and returns an int result

ToLongBiFunction<T,U>

A function that takes two parameters and returns a long result

ToLongFunction<T>

A function that takes a parameter and returns a long result

Instance

apply

Function<String, String> function = a -> a + " Jack!";
System.out.println(function.apply("Hello")); // Hello Jack!

compose

Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.compose(function1).apply("Hello");
System.out.println(greet); // Hello Bob! Jack!

andThen

Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.andThen(function1).apply("Hello");
System.out.println(greet); // Hello Jack! Bob!

Consumer< T> Consumer

Introduction

Overview

effect

Consume an object

scenes to be used

The forEach method of the Iterable interface needs to be passed in to Consumer. Most collection classes implement this interface to return an Iterator object for iteration.

Design ideas

When developers call ArrayList.forEach, they generally want to customize the consumption logic of traversal, such as output log or operation processing.
The processing logic is left to the user, and the use is flexible and changeable.
Changeable logic can be encapsulated into a class (implementing the Consumer interface) to extract the logic.

definition

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {
    //提供一个T类型的输入参数,不返回执行结果
    void accept(T t);

    //返回一个组合函数,after将会在该函数执行之后应用
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

All interfaces

interface

description

Consumer<T>

Provide an input parameter of type T without returning the execution result

BiConsumer<T,U>

Provide two input parameters of custom type, do not return the execution result

DoubleConsumer

Represents an operation that accepts a single double value parameter, but does not return a result

IntConsumer

Represents an operation that accepts a single int value parameter, but does not return a result

LongConsumer

Represents an operation that accepts a single long value parameter, but does not return a result

ObjDoubleConsumer<T>

Indicates that the object value and double value are accepted, but no operation result is returned

ObjIntConsumer<T>

表示接受object值和int值,但是不返回任何操作结果

ObjLongConsumer<T>

表示接受object值和long值,但是不返回任何操作结果

实例

accept

StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
consumer.accept(sb);
System.out.println(sb.toString());	// Hello Jack!

andThen

StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
Consumer<StringBuilder> consumer1 = (str) -> str.append(" Bob!");
consumer.andThen(consumer1).accept(sb);
System.out.println(sb.toString());	// Hello Jack! Bob!

Supplier< T >  供给型

简介

概述

作用

创建一个对象(工厂类)

使用场景

Optional.orElseGet(Supplier<? extends T>):当this对象为null,就通过传入supplier创建一个T返回。

设计思想

封装工厂创建对象的逻辑

定义

package java.util.function;

@FunctionalInterface
public interface Supplier<T> {
    //获取结果值
    T get();
}

不常用接口

接口

描述

Supplier<T>

不提供输入参数,但是返回结果的函数

BooleanSupplier

不提供输入参数,但是返回boolean结果的函数

DoubleSupplier

不提供输入参数,但是返回double结果的函数

IntSupplier

不提供输入参数,但是返回int结果的函数

LongSupplier

不提供输入参数,但是返回long结果的函数

实例

get

Supplier<String> supplier = () -> "Hello Jack!";
System.out.println(supplier.get()); // Hello Jack!

Predicate< T > 断言型接口

简介

概述

作用

  • 判断对象是否符合某个条件

使用场景

  • ​ArrayList的removeIf(Predicate):删除符合条件的元素
  • ​如果条件硬编码在ArrayList中,它将提供无数的实现,但是如果让调用者传入条件,这样ArrayList就可以从复杂和无法猜测的业务中解放出来。

设计思想

  • 提取条件,让条件从处理逻辑脱离出来,解耦合

定义

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {

    // 根据给定的参数进行判断
    boolean test(T t);

    // 返回一个组合判断,将other以短路与的方式加入到函数的判断中
    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);
    }

    // 返回一个组合判断,将other以短路或的方式加入到函数的判断中
    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<T>

对给定的输入参数执行操作,返回一个boolean类型的结果(布尔值函数)

BiPredicate<T,U>

对给定的两个输入参数执行操作,返回一个boolean类型的结果(布尔值函数)

DoublePredicate

对给定的double参数执行操作,返回一个boolean类型的结果(布尔值函数)

IntPredicate

对给定的int输入参数执行操作,返回一个boolean类型的结果(布尔值函数)

LongPredicate

对给定的long参数执行操作,返回一个boolean类型的结果(布尔值函数)

实例

test

Predicate<Integer> predicate = number -> number != 0;
System.out.println(predicate.test(10));    //true

and

Predicate<Integer> predicate = number -> number != 0;
predicate = predicate.and(number -> number >= 10);
System.out.println(predicate.test(10));    //true

or

Predicate<Integer> predicate = number -> number != 0;
predicate = predicate.or(number -> number != 10);
System.out.println(predicate.test(10));    //true

原理

其他网址

【Java8】Function 讲解_sowhat-CSDN博客

apply

        首先我们已经知道了Function是一个泛型类,其中定义了两个泛型参数T和R,在Function中,T代表输入参数,R代表返回的结果。也许你很好奇,为什么跟别的java源码不一样,Function 的源码中并没有具体的逻辑呢?

        其实这很容易理解,Function 就是一个函数,其作用类似于数学中函数的定义:y = f(x) ,(x,y)跟<T,R>的作用几乎一致。所以Function中没有具体的操作,具体的操作需要我们指定,apply具体返回的结果取决于传入的lambda表达式。

举例:

Function<Integer, Integer> test = i -> i + 1;
System.out.println(test.apply(5));

        用lambda表达式定义了一个行为使得i自增1,我们使用参数5执行apply,最后返回6。这跟我们以前看待Java的眼光已经不同了,在函数式编程之前我们定义一组操作首先想到的是定义一个方法,然后指定传入参数,返回我们需要的结果。函数式编程的思想是先不去考虑具体的行为,而是先去考虑参数,具体的方法我们可以后续再设置。

再举个例子:

public void test() {
    Function<Integer, Integer> test1 = i -> i + 1;
    Function<Integer, Integer> test2 = i -> i * i;
    /* print:6 */
    System.out.println(calculate(test1, 5));
    /* print:25 */
    System.out.println(calculate(test2, 5));
}

public static Integer calculate(Function<Integer, Integer> test, Integer number) {
    return test.apply(number);
}

        通过传入不同的Function,实现了在同一个方法中实现不同的操作。在实际开发中这样可以大大减少很多重复的代码,比如我在实际项目中有个新增用户的功能,但是用户分为VIP和普通用户,且有两种不同的新增逻辑。那么此时我们就可以先写两种不同的逻辑。除此之外,这样还让逻辑与数据分离开来,我们可以实现逻辑的复用。

        当然实际开发中的逻辑可能很复杂,比如两个方法F1,F2都需要操作AB,但是F1需要A->B,F2方法需要B->A。这样的我们用刚才的方法也可以实现,源码如下:

public void test() {
    Function<Integer, Integer> A = i -> i + 1;
    Function<Integer, Integer> B = i -> i * i;
    /* F1:36 */
    System.out.println("F1:" + B.apply(A.apply(5)));
    /* F2:26 */
    System.out.println("F2:" + A.apply(B.apply(5)));
}

compose和andThen

如上边例子所示,假如我们F1,F2需要四个逻辑ABCD,那我们还这样写就会变得很麻烦了。compose和andThen可以解决我们的问题。

先看compose的源码:compose接收一个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跟compose正相反,先执行当前的逻辑,再执行传入的逻辑:

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

这样说可能不够直观,我可以换个说法:compose等价于B.apply(A.apply(5)),而andThen等价于A.apply(B.apply(5))。

Function<Integer, Integer> A = i -> i + 1;
Function<Integer, Integer> B = i -> i * i;
/* F1:36 */
System.out.println("F1:" + B.apply(A.apply(5)));
/* F1:36 */
System.out.println("F1:" + B.compose(A).apply(5));
/* F2:26 */
System.out.println("F2:" + A.apply(B.apply(5)));
/* F2:26 */
System.out.println("F2:" + B.andThen(A).apply(5));

 

Guess you like

Origin blog.csdn.net/feiying0canglang/article/details/114154923