preface

Java 8 functional interface (Java 8) Java 8 functional interface (Java 8)

So what exactly is a functional interface?

To summarize: There is one and only abstract method, but there can be multiple interfaces to non-abstract methods.

The @functionalinterface annotation was added to Java 8 to define the interface as a FunctionalInterface.

The @functionalinterface annotation is not mandatory, as long as the interface conforms to the FunctionalInterface definition. However, if the interface does not conform to the FunctionalInterface definition, and the @functionalinterface annotation is added, the compiler will directly report an error.

The body of the

Java 8 has added a number of abstract functional interfaces, such as the usual Supplier, Consumer, Function, etc. These functional interfaces are defined under the java.util. Function package.

Here are some common interfaces:

Consumer

The Consumer interface, which receives the generic argument passed in, executes the Accept () method.

The main scenario of the Consumer interface, as you can see from the way the interface is named and defined, is to handle input parameters received, similar to the role of the Consumer.

Source code definition:

@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); }; }}Copy the code

Use posture:

public static void main(String[] args) {
	Consumer<String> consumer = (str) -> System.out.println(str);
  // 1. Execute the accept method
  consumer.accept("hello world!");
  // 2. Use with stream
  Stream.of("1"."2"."3").forEach(consumer);
}
Copy the code

Similar interfaces include BiConsumer, IntConsumer, DoubleConsumer, LongConsumer, etc. The difference is that they define different parameter types or can pass more than one generic parameter.

Supplier

Supplier, the provider interface, calls the get() method to return the generic T argument

Based on the naming of the interface and the way it is defined, the Supplier interface is mainly used for data generation, similar to the role of a provider.

Source code definition:

@FunctionalInterface
public interface Supplier<T> {

    T get(a);
}
Copy the code

Use posture:

public static void main(String[] args) {
	Supplier<Integer> supplier = () -> new Random().nextInt();
  System.out.println(supplier.get());
}
Copy the code

Similarly, there are IntSupplier, DoubleSupplier, LongSupplier, BooleanSupplier and other interfaces that return different data types.

Predicate

Predicate, Predicate, Predicate, Predicate, Predicate, Predicate, Predicate, Predicate

Source code definition:

@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(a) {
        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); }}Copy the code

Use posture:

public static void main(String[] args) {
		Predicate<Integer> predicate = (i) -> i > 5;
		System.out.println(predicate.test(6));
		System.out.println(predicate.test(1));
}
Copy the code

Function

Function, a functional interface that receives a generic T object and returns a generic R object.

It is mainly used for data processing and conversion. After processing the input data, it returns the output data required by specific requirements.

Source code definition:

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(a) {
        returnt -> t; }}Copy the code

As you can see, the apply(T T) method is the core Function for data conversion, but Function also provides the compose and andThen default methods.

  • Compose: Applies the parameters first and then the caller’s apply
  • AndThen: executes the caller first andThen the parameter, as opposed to compose

While the text may seem a little confusing, the examples below may be obvious

Use posture:

public static void main(String[] args) {
		Function<Integer, Integer> function = i -> i * 10;
    System.out.println(function.apply(2));

    // Perform 2 x 10 and then 20+1
    Function<Integer, Integer> com = i -> 1 + i;
    System.out.println(com.compose(function).apply(2));

    // Perform 2+2 and 4*10
    Function<Integer, Integer> andThen = i -> 2 + i;
    System.out.println(andThen.andThen(function).apply(2));
}
Copy the code

BiFunction, IntFunction, DoubleFunction, LongFunction, etc. The difference is that the type of the parameter is not the same or multiple generic parameters can be passed in.

conclusion

The java.util. Function package defines a number of functional abstract interfaces, and there are only a few that can be used for this purpose.

In many framework source code, this feature is used, because it not only greatly improves the simplicity of our code, but also improves the reuse of methods.

Ordinary change, will change ordinary

I am a house xiaonian, a low-key young man in the Internet

Please visit my blog at 📖 edisonz.cn for more shared articles