通辽公司做网站,网站常规seo优化步骤,长沙专业竞价优化公司,wordpress 用户界面几周前#xff0c;我写了关于Java 8 lambda的介绍 。 在本简介中#xff0c;我解释了什么是lambda以及如何将它们与Java 8中也引入的新Stream API结合使用。 Stream API为集合提供了更实用的接口。 此接口在很大程度上取决于lambda。 但是#xff0c;lambda不仅具有改进的收… 几周前我写了关于Java 8 lambda的介绍 。 在本简介中我解释了什么是lambda以及如何将它们与Java 8中也引入的新Stream API结合使用。 Stream API为集合提供了更实用的接口。 此接口在很大程度上取决于lambda。 但是lambda不仅具有改进的收集处理能力还具有更多优势 Lambda为您提供了构建更流畅的API的机会。 为了说明这一点作为示例我喜欢使用UserStore 它有助于使用数据库获取和保存用户。 它的公共API通常如下所示。 public interface UserStore {User find(Long id);ListUser findByLastname(String lastname);ListUser findByCompany(String company);..
} findBy方法的列表通常比我在此处包括的两个方法更长。 随着系统的发展可能还会有其他人。 尽管可行但实际上所有这些方法都可以完成相同的事情。 他们返回具有匹配特定值的属性的所有用户。 一些框架提供了解决此问题的方法。 如果您使用过Hibernate您可能会知道它们通过findByExample提供了解决方法其中您提供了User作为示例对象提供了查询的属性和值。 使用此示例对象中设置的任何值进行查询而从查询中排除任何为null字段。 您可以稍微调整一下这种行为但是这种方法存在许多问题。 考虑默认值必填字段即无法填写的字段 null 和不变性。 iBatisMyBatis以及Spring Data使用代码生成来节省您实现所有这些方法的时间而使API充满了findBy方法列表。 这些变通办法可能会走很长一段路但是它们确实留下了自己的特定问题。 另一种方法是使用lambda。 Lambda可以帮助我们将查询部分与过滤器规范分离。 让我们将findBy函数更改为接受lambda的单个函数。 public interface UserStore {User find(Long id);ListUser findBy(PredicateUser p);
} 那是一个更好的API。 显然谓词检查User对象有点天真。 您通常希望使用数据库查询进行过滤。 尽管如此它仍然很好地满足了本示例的目的您可以尝试使用自己的lambda来使用数据库查询进行过滤。 [注意 Predicate是Java 8附带的位于java.util.function包中。 至少在以前的API中这些谓词被捆绑在一个地方之前您可能会生气我们仍然可以捆绑通用谓词。 例如通过创建一个包含它们的实用程序类UserPredicates 。 public final class UserPredicates {public static PredicateUser lastname(String matcher) {return candidate - matcher.equals(candidate.getLastname());}
} 使用新的UserStore API变得非常简单。 static import UserPredicates.lastname;userStore.findBy(lastname(lastname); 不过 UserStore中还有一件事确实让我感到困扰。 find(id)函数返回一个用户。 但是如果没有这样的用户呢 可选的 为了对此进行改进我们可以并且应该查看Java 8的另一个新功能Optional。 这是monad的Java实现。 它看起来很像Scala的Option 。 使用Optional我们可以更好地表示一个函数可以返回一个值但不一定返回一个值并防止使用null 。 在我们的find(id)示例中返回Optional明确表示我们可能找到具有所请求ID的用户但可能不存在这样的用户。 public interface UserStore {OptionalUser find(Long id);ListUser findBy(Predicate p);
} 该API现在不仅记录了您可能会获得用户的事实而且从未返回null 。 我认为永不返回null的API更加安全。 有一天一个新的程序员可能没有意识到find可以返回null并且结果是一个null指针异常。 只是希望团队能够在生产之前就抓住它。 只要不使用null 就很容易防止空指针异常。 我们可以使用Optional上的函数从用户那里获取一个值如果有的话或者从一个默认值中获取一个值。 例如为了安全地获取用户的姓氏我们编写以下内容。 OptionalUser user userStore.find(id);
String lastname user.map(User::getLastname).orElse(); 这段代码表达力很强不需要太多解释。 如果有用户请获取其姓氏。 否则获取一个空字符串。 如果我们需要向用户发送密码重置电子邮件如果找到怎么办 OptionalUser user userStore.find(id);
user.ifPresent(passwordReset::send); 如果找到用户则发送密码重置否则什么也没有发生。 由于Java不像其他可能提供的其他语言例如HaskellClojure和Scala那样支持解构因此我们仅限于Optional的功能。 这使得Optional比任何一种其他语言的等效功能都弱。 建造者 当然不仅存储库的API都可以从lambda中受益。 Optional也是受益于lambda的API的一个很好的示例。 就我个人而言我还发现lambda特别有用可以代替过去的过往建造者。 通常不通过将特定的构建器传递给函数而是通过从函数中生成一个构建器来改善去耦。 让我向您展示一个示例用于发送电子邮件以阐明该想法。 public interface Mailer {void sendTextMessage(TextMessageBuilder message);void sendMimeMessage(MimeMessageBuilder message);
} 要使用Mailer我们需要将特定的构建器传递给它。 这些构建器具有通用的界面但是它们构建的消息类型不同。 Mailer具有不同的方法因为它必须根据所使用的类型添加不同的信息。 因此任何客户端代码都紧密耦合以传递正确的构建器。 您可能会怀疑这是lambda有用的地方。 Mailer函数可以创建所需的生成器并将其产生给lambda而不是要求客户端创建生成器并将其传递给客户端。 public interface Mailer {void sendTextMessage(MessageConfigurator configurator);void sendMimeMessage(MessageConfigurator configurator);FunctionalInterfaceinterface MessageConfigurator {MessageBuilder configure(MessageBuilder message);}
} 要使用Mailer我们要做的就是提供一个lambda来构建消息。 mailer.sendTextMessage(message -message.from(sender).to(recipients).subject(APIs).body(Lambdas can make for more fluent and stable APIs)
); API现在更加稳定。 客户端代码与特定构建器中的任何更改都脱钩并且只要构建器上的功能保持兼容就不会中断。 正如示例帮助我展示的那样lambda可以帮助您构建更流畅和稳定的API这些API更具意图。 这些API不需要太多的文档供其他程序员使用因为实际上很难使它们弄错。 作为一般准则我更喜欢清晰明了的代码而不是文档。 修复不记录。 当然我在本文中仅显示了一些示例。 Lambda不仅适用于此处的示例而且适用范围更广。 我希望本文能为您提供一些有关lambda可以帮助您的新见解并希望您能想到它们如何改善您的代码。 参考 Software Craft博客上的JCG合作伙伴 Bart Bakker 提供的Fluent和Stable API的Lambda 。 翻译自: https://www.javacodegeeks.com/2013/11/lambdas-for-fluent-and-stable-apis.html