内容简介:假设你已经使用了lambdas流,巨长的Stream的代码如下:以上实现功能是:计算上一年订购产品的次数。现在,只接受频繁订购的产品(> = 10)并返回它们,前提是如果它们没有被逻辑删除或显式隐藏在数据库中。你写完这段代码很快乐地回家了...
假设你已经使用了lambdas流,巨长的Stream的代码如下:
<b>public</b> List<Product> getFrequentOrderedProducts(List<Order> orders) {
<b>return</b> orders.stream()
.filter(o -> o.getCreationDate().isAfter(LocalDate.now().minusYears(1)))
.flatMap(o -> o.getOrderLines().stream())
.collect(groupingBy(OrderLine::getProduct, summingInt(OrderLine::getItemCount)))
.entrySet()
.stream()
.filter(e -> e.getValue() >= 10)
.map(Entry::getKey)
.filter(p -> !p.isDeleted())
.filter(p -> !productRepo.getHiddenProductIds().contains(p.getId()))
.collect(toList());
以上实现功能是:计算上一年订购产品的次数。现在,只接受频繁订购的产品(> = 10)并返回它们,前提是如果它们没有被逻辑删除或显式隐藏在数据库中。
你写完这段代码很快乐地回家了...
但我们会找到你的!管理层无法解雇你,谁可以读懂这堆代码?!谁愿意和你合作?
这段代码最糟糕的是每行返回不同的类型。除非您在IDE将鼠标悬停其中,否则你将看不到这些类型。
清洁代码最重要的规则之一是:小方法。所以,让我们通过查看我们.collect(..)后面看到的代码,将这个长链分成两个方法.stream()。既然你Collect了一个集合中的项目,为什么我们不通过提取一个好的方法名来解释那个集合是什么?
<b>public</b> List<Product> getFrequentOrderedProducts(List<Order> orders) {
<b>return</b> getProductCountsOverTheLastYear(orders).entrySet().stream()
.filter(e -> e.getValue() >= 10)
.map(Entry::getKey)
.filter(Product::isNotDeleted)
.filter(p -> !productRepo.getHiddenProductIds().contains(p.getId()))
.collect(toList());
}
<b>private</b> Map<Product, Integer> getProductCountsOverTheLastYear(List<Order> orders) {
<b>return</b> orders.stream()
.filter(o -> o.getCreationDate().isAfter(LocalDate.now().minusYears(1)))
.flatMap(o -> o.getOrderLines().stream())
.collect(groupingBy(OrderLine::getProduct, summingInt(OrderLine::getItemCount)));
}
但是,只有这样我们才注意到在第6行,我们可能会在循环中查询外部系统!我的天啊!这是你永远不应该做的事情。
让我们开始流之前先获得hiddenProductIds 列表,我们甚至可以进一步检查产品是否隐藏在Predicate局部变量中:
<b>public</b> List<Product> getFrequentOrderedProducts(List<Order> orders) {
List<Long> hiddenProductIds = productRepo.getHiddenProductIds();
Predicate<Product> productIsNotHidden = p -> !hiddenProductIds.contains(p.getId());
<b>return</b> getProductCountsOverTheLastYear(orders).entrySet().stream()
.filter(e -> e.getValue() >= 10)
.map(Entry::getKey)
.filter(Product::isNotDeleted)
.filter(productIsNotHidden)
.collect(toList());
还有一件事我们可以做:我们可以命名被频繁订购的产品的流,并使其成为Stream类型的变量。众所周知,这些Stream项目实际上并未在此时进行计算评估,而是仅在结束时.collect()进行计算评估。但是,Stream<>有时不鼓励使用变量,因为粗心的开发人员可能会尝试重新使用它(重新遍历它),因此在执行此操作之前,请确保您的团队完全了解这种常见情况。
<b>public</b> List<Product> getFrequentOrderedProducts(List<Order> orders) {
List<Long> hiddenProductIds = productRepo.getHiddenProductIds();
Predicate<Product> productIsNotHidden = p -> !hiddenProductIds.contains(p.getId());
Stream<Product> frequentProducts = getProductCountsOverTheLastYear(orders).entrySet().stream()
.filter(e -> e.getValue() >= 10)
.map(Entry::getKey);
<b>return</b> frequentProducts
.filter(Product::isNotDeleted)
.filter(productIsNotHidden)
.collect(toList());
}
<p>[...]
这里的想法是通过引入解释变量来避免过多的方法链。这意味着 提取方法甚至使用函数或Stream类型的变量,以使代码尽可能清晰地显示给读者。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Everything Store
Brad Stone / Little, Brown and Company / 2013-10-22 / USD 28.00
The definitive story of Amazon.com, one of the most successful companies in the world, and of its driven, brilliant founder, Jeff Bezos. Amazon.com started off delivering books through the mail. Bu......一起来看看 《The Everything Store》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
XML 在线格式化
在线 XML 格式化压缩工具