New features of JDK1.8 (four): functional interface

New features of JDK1.8 (four): functional interface

The last article about Lambda expressions makes you love it . It simply talks about the syntax and usage of Lambda expressions, which makes you feel good about it. You may not know how Lambda expressions are implemented and defined. This article will introduce the functional interface in detail , so that you can be aware and confident when using the new features of the JDK.

1. functional interface

Functional interface (

functional Interface
), an interface with one and only one abstract method , but there can be multiple non-abstract methods.

Applies to the interface used by Lambda expressions. Such as creating a thread:

new Thread(() -> System.out.println(Thread.currentThread().getName())).start(); Copy code

Among them, the Lambda expression replaces

new Runnable()
,here
Runable
The interface is a functional interface, the most intuitive embodiment is the use of
@FunctionalInterface
Annotation, and an abstract method (there is only one) is used, as follows:

package java.lang; /** * The <code>Runnable</code> interface should be implemented by any * class whose instances are intended to be executed by a thread. The * class must define a method of no arguments called <code>run</code>. * <p> * This interface is designed to provide a common protocol for objects that * wish to execute code while they are active. For example, * <code>Runnable</code> is implemented by class <code>Thread</code>. * Being active simply means that a thread has been started and has not * yet been stopped. * <p> * In addition, <code>Runnable</code> provides the means for a class to be * active while not subclassing <code>Thread</code>. A class that implements * <code>Runnable</code> can run without subclassing <code>Thread</code> * by instantiating a <code>Thread</code> instance and passing itself in * as the target. In most cases, the <code>Runnable</code> interface should * be used if you are only planning to override the <code>run()</code> * method and no other <code>Thread</code> methods. * This is important because classes should not be subclassed * unless the programmer intends on modifying or enhancing the fundamental * behavior of the class. * * @author Arthur van Hoff * @see java.lang.Thread * @see java.util.concurrent.Callable * @since JDK1.0 */ @FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); } Copy code

1. Format

Modifier interface interface name {

public abstract return value type method name (optional parameter list);

}

Note:

public abstract
Can be omitted (because the default modification is
public abstract
)

Such as:

public interface MyFunctionalInterface { public abstract void method(); } Copy code

2. Annotation @FunctionalInterface

@FunctionalInterface
, Is a new annotation introduced in JDK1.8, specifically refers to the functional interface, used in the definition of an interface.

with

@Override
Annotation works similarly,
@FunctionalInterface
Annotations can be used to detect whether the interface is a functional interface. If it is a functional interface, the compilation is successful, otherwise the compilation fails (there is no abstract method in the interface or the number of abstract methods is more than 1).

package com.xcbeyond.study.jdk8.functional; /** * Functional interface * @Auther: xcbeyond * @Date: 2020/5/17 0017 0:26 */ @FunctionalInterface public interface MyFunctionalInterface { public abstract void method(); //If there are multiple abstract methods, the compilation fails, that is: @FunctionalInterface is red //public abstract void method1(); } Copy code

3. Examples

Functional interface:

package com.xcbeyond.study.jdk8.functional; /** * Functional interface * @Auther: xcbeyond * @Date: 2020/5/17 0017 0:26 */ @FunctionalInterface public interface MyFunctionalInterface { public abstract void method(); //If there are multiple abstract methods, the compilation fails, that is: @FunctionalInterface is red //public abstract void method1(); } Copy code

test:

package com.xcbeyond.study.jdk8.functional; /** * Test functional interface * @Auther: xcbeyond * @Date: 2020/5/17 0017 0:47 */ public class MyFunctionalInterfaceTest { public static void main(String[] args) { //Call the show method, there is a functional interface MyFunctionalInterface in the parameter, so you can use Lambda expressions to complete the implementation of the interface show("hello xcbeyond!", msg -> System.out.printf(msg)); } /** * Define a method, the parameter uses the functional interface MyFunctionalInterface * @param myFunctionalInterface */ public static void show(String message, MyFunctionalInterface myFunctionalInterface) { myFunctionalInterface.method(message); } } Copy code

Functional interface, is it more flexible to use, you can implement the interface at the specific call site.

The functional interface can support Lambda expressions friendly.

2. Commonly used functional interfaces

There were a lot of functional interfaces before JDK1.8, the most familiar is

java.lang.Runnable
Interface.

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

And added in JDK1.8

java.util.function
Many functional interfaces under the package are used to support functional programming in Java, thus enriching the usage scenarios of Lambda expressions.

Here are mainly four core functional interfaces:

  • java.util.function.Consumer
    : Consumer interface
  • java.util.function.Supplier
    : Supply interface
  • java.util.function.Predicate
    : Deterministic interface
  • java.util.function.Function
    : Functional interface

1. Consumer interface

java.util.function.Consumer
The interface is a consumer interface, and the consumption data type is determined by the generic.

package java.util.function; import java.util.Objects; /** * Represents an operation that accepts a single input argument and returns no * result. Unlike most other functional interfaces, {@code Consumer} is expected * to operate via side-effects. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #accept(Object)}. * * @param <T> the type of the input to the operation * * @since 1.8 */ @FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> {accept(t); after.accept(t); }; } } Copy code

(1) Abstract method: accept

Consumer
Abstract method in interface
void accept(T t)
, Used to consume a specified generic T data.

Examples are as follows:

/** * Test void accept(T t) */ @Test public void acceptMethodTest() { acceptMethod("xcbeyond", message -> { //Complete the processing of the string, that is: use the accept method of the Consumer interface to consume the corresponding data type (generic) String reverse = new StringBuffer(message).reverse().toString(); System.out.printf(reverse); }); } /** * Define a method for consuming message strings * @param message * @param consumer */ public void acceptMethod(String message, Consumer<String> consumer) { consumer.accept(message); } Copy code

(2) Method: andThen

method

andThen
, Can be used to combine multiple
Consumer
The interfaces are connected together to complete data consumption.

/** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> {accept(t); after.accept(t); }; } Copy code

Examples are as follows:

/** * Test Consumer<T> and Then(Consumer<? super T> after) * Output result: * XCBEYOND * xcbeyond */ @Test public void andThenMethodTest() { andThenMethod("XCbeyond", t -> { //Convert to size output System.out.println(t.toUpperCase()); }, t -> { //Convert to lowercase output System.out.println(t.toLowerCase()); }); } /** * Define a method to connect two Consumer interfaces together for consumption * @param message * @param consumer1 * @param consumer2 */ public void andThenMethod(String message, Consumer<String> consumer1, Consumer<String> consumer2) { consumer1.andThen(consumer2).accept(message); } Copy code

2. Supplier interface

java.util.function.Supplier
The interface is a supply-type interface, namely: a production-type interface. Contains only one method without parameters:
T get()
, Used to obtain data of the type specified by a generic parameter.

package java.util.function; /** * Represents a supplier of results. * * <p>There is no requirement that a new or distinct result be returned each * time the supplier is invoked. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #get()}. * * @param <T> the type of results supplied by this supplier * * @since 1.8 */ @FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); } Copy code

Examples are as follows:

@Test public void test() { String str = getMethod(() -> "hello world!"); System.out.println(str); } public String getMethod(Supplier<String> supplier) { return supplier.get(); } Copy code

3. Predicate interface

java.util.function.Predicate
The interface is a predicate interface, used to judge the specified type of data, and get a judgment result (
boolean
Type value).

package java.util.function; import java.util.Objects; /** * Represents a predicate (boolean-valued function) of one argument. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #test(Object)}. * * @param <T> the type of the input to the predicate * * @since 1.8 */ @FunctionalInterface public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate<T> negate() { return (t) -> !test(t); } /** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param <T> the type of arguments to the predicate * @param targetRef the object reference with which to compare for equality, * which may be {@code null} * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } } Copy code

(1) Abstract method: test

Abstract method

boolean test(T t)
, Used for condition judgment.

/** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); Copy code

Examples are as follows:

/** * Test boolean test(T t); */ @Test public void testMethodTest() { String str = "xcbey0nd"; boolean result = testMethod(str, s -> s.equals("xcbeyond")); System.out.println(result); } /** * Define a method for character string judgment. * @param str * @param predicate * @return */ public boolean testMethod(String str, Predicate predicate) { return predicate.test(str); } Copy code

(2) Method: and

method

Predicate<T> and(Predicate<? super T> other)
, Used to combine two
Predicate
Make logical "and" judgments.

/** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); }

3 negate

Predicate<T> negate()

/** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate<T> negate() { return (t) -> !test(t); }

4 or

Predicate<T> or(Predicate<? super T> other)
Predicate

/** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); }

4. Function

java.util.function.Function

package java.util.function; import java.util.Objects; /** * Represents a function that accepts one argument and produces a result. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #apply(Object)}. * * @param <T> the type of the input to the function * @param <R> the type of the result of the function * * @since 1.8 */ @FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * 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; } }

1 apply

R apply(T t)
T R

/** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t);

/** * R apply(T t) */ @Test public void applyMethodTest() { // String numStr = "123456"; Integer num = applyMethod(numStr, n -> Integer.parseInt(n)); System.out.println(num); } public Integer applyMethod(String str, Function<String, Integer> function) { return function.apply(str); }

2 compose

<V> Function<V, R> compose(Function<? super V, ? extends T> before)
,
apply
function

/** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); }

3 andThen

<V> Function<T, V> andThen(Function<? super R, ? extends V> after)
,

/** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }

Java

Java JDK1.8 JDK1.8 JDK1.8

Lambda Lambda

CPU java Lambda Lambda

JDK1.8 Stream

1.

2.

(x, y) -> x y

3.

unit testing debugging

4. " "

" " " " " "

5.

JDK1.8/JDK1.8

JDK1.8

1.www.cnblogs.com/Dorae/p/776

2.blog.csdn.net/stormkai/ar

3.baike.baidu.com/item/