上篇 java8新特性之Lambda表达式,说了如下java8 Lambda的基本语法,再来讲一下 函数式接口。你会发现每次运用时,都会有一个接口类型来接收,它有一个专门的名字叫函数式接口,可是并非每一个接口均可以叫函数式接口,必须知足有且只有一个抽象方法的条件,而且还有如下的特色。
线程接口Runnable就是一个典型的函数式接口
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(); }
咱们也能够本身定义函数式接口,定义一个接口,使用lambda表达式传递接口而且调用
/** * 函数式接口 */ @FunctionalInterface //只是为了编译器检查 能够不写 public interface MyInterface { // 有且只有一个抽象方法 void sayHello(String name); //1.能够重写 Object的toString方法 @Override String toString(); // 也能够重写 Object的equals方法,还能够重写其余方法,这里只举个例子 @Override boolean equals(Object object); //2 能够有默认方法 default void sayHi(String name) { System.out.println("hi :" + name); } //3 能够有静态方法 static boolean isEqual(Object obj) { return (null == obj) ? true : false; } } -------------------------------------- @Test public void test() { // 调用 须要一个String参数 而后打印输出 say("black猫", (name) -> System.out.println(name + ": hello")); } /** * 声明一个 接口传递方法 * @param name 接口须要的参数 * @param myInterface 是函数式类型接口 */ public void say(String name, MyInterface<String> myInterface) { myInterface.sayHello(name); }
其实咱们不用本身定义这些函数式接口,java8给咱们内置好了一些接口以下:
Consumer接口除了一个抽象方法accept(T t)还有一个默认实现的andThen(Consumer consumer),用来在前一个消费接口调用完accept()后使用,能够理解为一个连续性操做。
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); }; } }
1.Consumer接口的accept消费一个参数(反转字符串)html
@Test public void test01(){ testConsumer01("hello",(msg)->System.out.println(new StringBuffer(msg).reverse().toString()); } //调用 accept public void testConsumer01(String str,Consumer<String> consumer){ consumer.accept(str); }
2.两个消费接口 调用accept,实现一个输出字符串大写,一个输出字符串输出小写java
@Test public void test02(){ testConsumer02("Hello Lambda",(str)->{ System.out.println(str.toUpperCase()); },(str)->{ System.out.println(str.toLowerCase()); } ); } //两个消费接口 调用 accept public void testConsumer02(String str,Consumer<String> consumer1,Consumer<String> consumer2){ consumer1.accept(str); consumer2.accept(str); }
3.两个消费接口的accept和andThen组合操做字符app
@Test public void test03() { String[] names = {"张山,男", "李诗,女", "王武,男", "马柳,女"}; testConsumer03(names, (str) -> { System.out.print(str.split(",")[0]+":"); }, (str) -> { System.out.println(str.split(",")[1]); } ); } public void testConsumer03(String[] names, Consumer<String> consumer1, Consumer<String> consumer2) { for (int i = 0; i < names.length; i++) { //第一个消费接口处理完,第二个消费接口接着处理 consumer1.andThen(consumer2).accept(names[i]); } }
提供一个抽象方法get(),返回一个T
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(); }
利用供给型接口获取10个100内随机数,输出
@Test public void test04() { ArrayList<Integer> arr = testSupplier02(10, () -> (int) (Math.random()*100)); for (int i = 0; i < arr.size(); i++) { System.out.println(i + arr.get(i)); } } public ArrayList<Integer> testSupplier02(int size, Supplier<Integer> consumer) { ArrayList<Integer> arr = new ArrayList<>(); for (int i = 0; i < size; i++) { int str = consumer.get(); arr.add(str); } return arr; }
提供一个抽象方法apply(T t),返回一个R,Function<T,V> compose(Function function)在apply前执行,Function<T,V> andThen(Function function)在apply以后执行。
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; } }
把一个字符串,先转大写而后反转,最后转小写打印,采用三个函数型接口参数
@Test public void test3() { String msg = textFunction("hello-LAmbda", (str1) -> { return str1.toUpperCase(); },(str1)->{ return str1.toLowerCase(); },(str1)->{ return new StringBuilder(str1).reverse().toString(); }); System.out.println(msg); } public String textFunction(String str, Function<String, String> function, Function<String, String> function2, Function<String, String> function3) { // function先执行而后是function2,可是function3在function2以前执行因此function2最后执行~~~ return function.andThen(function2.compose(function3)).apply(str); }
一个抽象方法test(Test t),默认方法 and(Predicate predicate)/or(Predicate predicate)/negate(Predicate predicate)静态方法isEqual(Object targetRef)
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); } }
判断一个字符串是否包含‘*’而且长度大于10 或者 字符串包含‘-’
public void test4() { String str = "hello-lambda"; boolean bool = textPredicate(str, (msg) -> { return msg.indexOf('*') > -1; }, (msg) -> { return msg.length() > 10; }, (msg) -> { return msg.indexOf("-") > -1; }); System.out.println(bool); } public boolean textPredicate(String str, Predicate<String> predicate, Predicate<String> predicate2, Predicate<String> predicate3) { return predicate.and(predicate2).or(predicate3).test(str); }
根据上面的示例,每一个接口结合源码能够写出本身想要的代码
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
BiFunction<T, U, R> | T, U | R | 对类型为 T, U 参数应用 操做,返回 R 类型的结 果。包含方法为 R apply(T t, U u); |
UnaryOperator<T> (Function子接口) | T | T | 对类型为T的对象进行一 元运算,并返回T类型的 结果。包含方法为 T apply(T t); |
BinaryOperator<T> (BiFunction 子接口) | T, T | T | 对类型为T的对象进行二 元运算,并返回T类型的 结果。包含方法为 T apply(T t1, T t2); |
BiConsumer<T, U> | T, U | void | 对类型为T, U 参数应用 操做。包含方法为 void accept(T t, U u) |
ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T> | T | int long double | 分别计算int、long、 double、值的函数 |
IntFunction<R> LongFunction<R> DoubleFunction<R> | int long double | R | 参数分别为int、long、 double 类型的函数 |
函数式接口是构建lambda表达式的一个前提,只有弄清楚了,接口的定义参数和返回类型,后面的lambda表达式按照语法格式就好写了,接口做为参数能够传多个,根据相应的方法,组合搭配出本身想要的功能。使用每个接口首先看如下源码每一个方法的做用而后熟练应用能够学的更快。
文章首发于 黑猫のBlog 欢迎来留言啊!!!less