传递Runnable创建Thread
Thread thread=new Thread(new Runnable() { @Override public void run() { // do something } });
new Thread(()->{});
上边的例子比较简单,但是有两个疑问。 什么是 Lambda表达式? 怎么使用 lambda表达式?
从上述例子入手,首先我们知道 Lambda一般代表的是一个匿名对象 ;其次我们点击“->”,IDE会帮助我们进入到符合Lambda规范的函数接口。我们来观察下这个符合规范的类的变化。
// 省略注释 package java.lang; public interface Runnable { public abstract void run(); }
// 省略注释 package java.lang; @FunctionalInterface public interface Runnable { public abstract void run(); }
我们发现java8后Runnable接口新增了一个注解@FunctionalInterface。下边我们一起来看下这个注解是什么。
/** * An informative annotation type used to indicate that an interface * type declaration is intended to be a <i>functional interface</i> as * defined by the Java Language Specification. * * Conceptually, a functional interface has exactly one abstract * method. Since {@linkplain java.lang.reflect.Method#isDefault() * default methods} have an implementation, they are not abstract. If * an interface declares an abstract method overriding one of the * public methods of {@code java.lang.Object}, that also does * <em>not</em> count toward the interface's abstract method count * since any implementation of the interface will have an * implementation from {@code java.lang.Object} or elsewhere. * * <p>Note that instances of functional interfaces can be created with * lambda expressions, method references, or constructor references. * * <p>If a type is annotated with this annotation type, compilers are * required to generate an error message unless: * * <ul> * <li> The type is an interface type and not an annotation type, enum, or class. * <li> The annotated type satisfies the requirements of a functional interface. * </ul> * * <p>However, the compiler will treat any interface meeting the * definition of a functional interface as a functional interface * regardless of whether or not a {@code FunctionalInterface} * annotation is present on the interface declaration. * * @jls 4.3.2. The Class Object * @jls 9.8 Functional Interfaces * @jls 9.4.3 Interface Method Body * @since 1.8 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {}
好了,从上边我们知道了lambda的特点,接下来我们来聊下怎么使用?
首先,我们去官网查阅Java8 新特性 ,找到 Lambda表达式 的说明。我们从这个文档的**“Syntax of Lambda Expressions”**部分入手,大概可以得到如下的结论。
Lambda主要由下边几部分组成;参数列表,连接符,主体。
{ System.out.println("xxx"); }
{ // do something return some result return 100; }
目的,将具体业务实现交给调用者处理。
interface Print<String>{ void printName(String string); }
我这里的业务逻辑是根据输入参数,执行日志打印操作。实际业务场景下,可能对应的是发送邮件或者MQ这样的具体操作。
public class LambdaDemo { public static void main(String[] args) { PrintSomeThing(name->System.out.println(name),"Hello baigt"); } public static void PrintSomeThing(Print<String> str,String name) { str.printName(name); } }
class Doctor{ String name; String interest; public Doctor(String name, String interest) { this.name = name; this.interest = interest; } public void printName(Print<String> str) { str.printName(name); } }
Doctor doctor=new Doctor("baigt","java and javascript"); doctor.printName(name->System.out.println(name));
目的,将具体业务实现交给调用者处理,并将结果返回。
interface GetSomething<String>{ String getThing(); }
class Doctor{ String name; String interest; public Doctor(String name, String interest) { this.name = name; this.interest = interest; } public String getInterest(GetSomething<String> get) { return get.getThing()+","+name; } }
我这里的业务逻辑是根据输入参数(隐式interest),计算出一个结果返回出来,并对这个结果执行打印操作。
Doctor doctor=new Doctor("baigt","java and javascript"); System.out.println(doctor.getInterest(() -> "Hi"));
到此处,我们已经大概明白lambda表达式的基本用法。但是还会有两个疑问?
我们选中@FunctionInterface注解类,通过Ide的Find Usages功能,会发现在java.util.function包下java8新增了很多类。这里挑几个基础的(其他的基本是功能上的增强或变种)来说。大致上有这么几种。
下边会做一个简单的说明和使用。可能不会细致的去讲每一个Api。旨在让大家快速熟悉使用java8 lambda。
/** * 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); }; } }
首先此接口只有一个抽象方法accept, 该方法接收一个入参,不返回结果 。
public static void doConsumer(Consumer consumer,String input) { consumer.accept(input); }
接收 “something input”输入,并执行打印操作
Consumer consumer = input -> System.out.println(input); doConsumer(consumer,"something input");
将两个Consumer操作串连起来,andThen的后执行。
Consumer consumer = input -> System.out.println(input); doConsumer(consumer.andThen(input2->{ System.out.println("input2"); }),"something input");
/** * 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(); }
首先此接口只有一个抽象方法get, 该方法不接收参数,返回一个T类型的结果 。
public static <T> T doSupplier(Supplier<T> supplier) { return supplier.get(); }
不传入参数,生成一个指定类型为String或Integer的对象
System.out.println(doSupplier(() -> "baigt")); System.out.println(doSupplier(() -> {return Integer.valueOf("10");}));
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); } }
首先此接口只有一个抽象方法test, 该方法接受一个T类型的对象,返回一个boolean类型的结果 。
public static boolean doPredicate(Predicate<String> predicate,String string) { return predicate.test(string); }
根据条件,判断输入对象是否符合过滤规则。
System.out.println(doPredicate(input -> input.length() > 5, "12345")); System.out.println(doPredicate(((Predicate<String>) (input -> input.length() > 5)) .and(input -> input.equalsIgnoreCase("12345")), "12345"));
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; } }
首先此接口只有一个抽象方法apply, 该方法接收一个T类型对象,返回一个R类型的结果。
public static Integer doFunction(Function<String,Integer> function,String input) { return function.apply(input); }
接收一个String类型的入参,返回Integer类型的结果。示例中没做具体异常判断。
System.out.println(doFunction(input -> input.length(), "baigt")); // 上述结果为 5 System.out.println(doFunction(((Function<String, Integer>) (input -> input.length())).compose(input -> String.valueOf(input.length() * 3)), "baigt")); // 上述结果为 2 System.out.println(doFunction(((Function<String, Integer>) (input -> { System.out.println("notcompose:"+input); return Integer.valueOf(input)+1; })).compose(input -> { System.out.println("compose:"+input); return String.valueOf(Integer.valueOf(input)*3); }), "22")); // 上述结果为 67
compose是先执行的部分,上述例子中,是根据输入参数进行进一步的加工,再作为输入参数传递给具体调用者。
前边提到了方法引用和构造引用两种,其实构造引用是一种特殊方法引用。具体参照 官方文档说明 中“Kinds of Method References”部分。
种类 | 用例 |
---|---|
类名::静态方法 | String::valueOf |
实例对象::实例方法 | doctor1::getInterest |
类名::实例方法 | String::toUpperCase |
类名::new (构造引用) | String::new |
public static String doStaticReference(Function<Integer,String> function, Integer input) { return function.apply(input); }
doStaticReference(String::valueOf,123456);
class Doctor{ String name; String interest; public Doctor(String name, String interest) { this.name = name; this.interest = interest; } public String getStringInstance(){ return new String(name); } }
Doctor doctor1=new Doctor("baigt007","java"); Supplier<String> instance = doctor1::getInterest;
public static String doMethodReference(Function<String,String> function, String input) { return function.apply(input); }
doMethodReference(String::toUpperCase,"baigt");O
Supplier<String> stringInstance = String::new;
上述是个人心得,不对之处,欢迎指正。
作者:baigt 交流群:244930845