Lambda表达式进一步探讨

Lambda表达式的运用

尼玛,噩耗啊。项目居然要用Angular js,我擦,国内看文档都要翻墙的说。。。 对于这个也是一知半解,看来学习mode需要强势开启。。。 继续说说Lambda吧。

利用泛型

还拿回上一篇(link可点)的例子。

interface CheckPerson {boolean test(Person p);}

我们做一些改动:

interface Predicate<T> {boolean test(T t);}

之前接受的领域模型是Person,而修改之后我们的领域模型是T,可以动态绑定任何领域模型。 如果我们指定这个领域模型是Person的时候,那么这个接口其实就是下面的效果:

interface Predicate<Person> {boolean test(Person t);}

那么实现的class可以写成这个样子:

<(Person t) {return false;}}

有个泛型我们可以随意指定领域模型来进行领域模型扩充。

看回我们上一篇的例子。

(List<Person> roster, Predicate<Person> tester) {for (Person p : roster) {if (tester.test(p)) {p.printPerson();}}}

这个定义的方法printPersonsWithPredicate,我们调用的时候依然可以利用Lambda表达式:

printPersonsWithPredicate(roster,p -> p.getGender() == Person.Sex.MALE&& p.getAge() >= 18&& p.getAge() <= 25);

来完成。并且今后如果不是Person的class的话也可以动态的在Lambda的表达式中指定。

Lambda表达式的纵向贯穿和优化

上面利用泛型后可以扩充领域模型,但是例子中还是有一个问题。

(List<Person> roster, Predicate<Person> tester) {for (Person p : roster) {if (tester.test(p)) {p.printPerson();}}}

仔细看上面的代码,我们的tester.test(Person p)这个方法利用Lambda表达式拉到了方法调用的地方来具体实现,但是这个printPersonsWithPredicate方法中还调用了一个p.printPerson()的方法,也就是说,当我们如果对Person的printPerson进行调整的话,势必要影响到这个printPersonsWithPredicate方法自身的逻辑和实现。利用Lambda表达式的一个最重要的目的也是为了提取函数式接口中的唯一这个方法的逻辑使其轻巧地在调用的地方得到体现,而不去影响调用方法本身的逻辑,从代码的编程层面上进行了一个神似的解耦操作。所以上面的这个p.printPerson()并没有得到“解耦“,利用Lambda表达式还有一个优化的可能性。 我们都知道能量守恒以及时间空间的转换,任何事物都有其本质和内在的互联,我们节省了时间空间势必要有上升,反之亦然。那么上面这个问题的解决方法就是利用空间换取灵巧。 可以思考下面的这种模式: 我们首先定义一个interface:

accept(T t);}

OK,这是一个函数式接口。不知道函数式接口的请参看:上一篇:Lambda初体验 当然,其实我们可以不用定义这个interface,,java的最新的java.util.function的package中已经为我们定义了这么一个可以直接使用的函数式接口,代码拿来看看:

先来了解 java.util.function 中的Consumer<T> * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.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 */<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); };}}

这是一个函数式接口,满足一个abstract方法和≧1个的default或者static方法。 那么这个interface中的void accept(T t)即我们可以利用的方法,进行逻辑的实现。 这个interface中的default方法是被所有implement这个接口的方法所。。。。嗯。。我靠,这里怎么说?继承?呵呵,终于可以说一个类继承了一个接口的方法,这在以前也算是一个业余的错误说法吧。 所有实现这个interface的class都可以默认地拥有这个addThen方法,这个方法的目的就是在我们做完accept方法后可以继续使用一个T来完成一个后处理的执行。 举个简单的例子,比如这个场景:我们想在执行p.printPerson()后再执行一下p.printPerson2()的方法,那么这个printPerson2()就是所谓的后处理。 假设Person的中的方法是:

() {System.out.println(1);// …}() {System.out.println(2);// …}

调用:

Consumer<Person> impl = (Person p) -> p.printPerson(); // 行1impl.andThen((Person p) -> p.printPerson2()); // 行2没有什么可留恋,只有抑制不住的梦想,

Lambda表达式进一步探讨

相关文章:

你感兴趣的文章:

标签云: