【问题标题】:Strange looking guava code奇怪的番石榴代码
【发布时间】:2013-07-10 03:46:36
【问题描述】:

我在执行以下代码 sn-p 时遇到问题:

prices = pricesService.getProductsByCategory(category);
List<Double> discountedPrices = 
    Lists.newArrayList(Iterables.transform(prices, new Function<Double, Double>() {
        public Double apply(final Double from) {
            return from *.88;
        }
    }));

我知道代码的结果是什么,并且在单元测试中是正确的,但我不太熟悉番石榴或这个实现如何/为什么工作。此外,如果列表“价格”中存在空值,目前似乎也不安全?所以我追求的是:

  1. 代码工作原理的一般说明。
  2. 目前是否为空安全?如果不是,它怎么会变成这样?

【问题讨论】:

  • 哪一部分给你带来了麻烦?您是否阅读过.transform 的文档?看起来如果链中没有任何内容过滤掉空值,那么如何使其成为空值安全将是相当明显的,尽管您需要定义在这种情况下您实际希望发生的事情。
  • 我想这对我来说有点陌生。将“转换”视为方法名称有点让我头疼。至于 null 部分,我会检查是否 from == null 我猜?不确定函数调用是否有不同之处?
  • transform 作为方法名有什么问题?
  • 当您了解这段代码在做什么时,请务必阅读:code.google.com/p/guava-libraries/wiki/FunctionalExplained(并测试命令式和函数式方法的性能)。
  • “Null safe”是一个具有误导性的术语。另一个短语可能是“不会告诉您代码中可能指示细微错误的空定时炸弹。”

标签: java guava


【解决方案1】:

它创建了一个新的双精度列表,它是原始的 0.88 *。

结构是:

匿名内部类

这是在 Java 中有时如何完成回调/闭包的一种方式。另请参阅Java tutorial

new Function<Double, Double>() {
    public Double apply(final Double from) {
        return from *.88;
    }
}

使用上述函数回调

Iterables.transform(prices, *func*)

将结果转换为 ArrayList

上面的结果是一个Iterable,所以需要存储到一个列表中。另见Lists.newArrayList vs new ArrayList

Lists.newArrayList( ... )

【讨论】:

  • 所以或多或少这是一种解决这个问题的函数式编程风格?在 Java 中没有看到太多的函数行为!很棒的链接,谢谢!
  • 有点,是的......在下一个 Java SE 中可能会有一个语法简写,并且这种风格会变得更简洁,采用 Groovy 风格。
  • 顺便说一句,这种风格在一些 web 框架中被大量使用,例如。检票口
【解决方案2】:

1) 所以 Guava 有一个名为 Iterables 的静态 util 类,它有一个名为 transform 的方法,它接受一个集合和一个 guava Function 实例作为变量。在这种情况下,开发人员使用了一个内联匿名函数,该函数通过覆盖的方法“apply”返回一个双精度值。

更传统的实现应该是这样的:

List<Double> discountedPrices = Lists.newArrayList();
for(Double price: prices) {
    discountedPrices.add(price * .88);
}

2) 不完全确定您所说的 null 安全是什么意思?假设您的意思是如果列表“价格”包含空值会发生什么?如果是这样,番石榴在 Iterables.filter(Collection, Predicate) 中为您提供了另一种解决方案。在您的情况下,您希望过滤掉空值,并且为此目的有一个内置的番石榴谓词。因此,在您的情况下,您可以执行以下操作:

 prices = Iterables.filter(prices, Predicates.notNull();
 List<Double> discountedPrices = Lists.newArrayList(
 Iterables.transform(prices, new Function<Double, Double>() {
        public Double apply(final Double from) {
            return from *.88;
        }
    }));

第一行返回没有空值的价格集合,第二行的行为与以前完全相同,您可以安全地假设空值已被删除。

【讨论】:

  • filter 必须在transform 之前应用,而不是之后。否则from *.88 中的隐式拆箱将抛出NullPointerException
猜你喜欢
  • 2016-11-03
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多