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 (
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
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:
Such as:
public interface MyFunctionalInterface { public abstract void method(); } Copy code
2. Annotation @FunctionalInterface
with
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
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
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
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
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
/** * 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
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
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
/** * 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
/** * 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
/** * 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
/** * 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
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
/** * 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
/** * 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
/** * 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.
3.
unit testing debugging
4. " "
" " " " " "
5.
JDK1.8/JDK1.8
JDK1.8