Guava是否有类似于Python的reduce函数的等效函数?

20

2
Java SE 8可能会在添加lambda后增加Collections.reduce。顺便说一下,Python 3鼓励使用显式的for循环代替reduce;reduce已从内置函数移动到functools模块中。 - ide
1
@ide:可能会有一个Collection.reduce方法,因为会有扩展方法。我知道他们计划添加像filtermap这样的扩展方法。 - ColinD
1
不确定,只是一条评论... http://code.google.com/p/lambdaj/ 是否支持? - CurtainDog
1
请查看http://functionaljava.org。 - gpampara
8个回答

7

不行。虽然像这样的功能最终可能会被添加,但这并不是Guava的核心重点。请参见此问题


6
我尚未找到任何支持map和reduce的Java集合库。(我排除并行/分布式处理框架中的map/reduce功能......因为您需要一个“大”问题才能使这些框架有价值。)可能,这种“缺乏”的原因是没有闭包的map/reduce编码过于繁琐。太多样板代码,太多重量级语法。由于在简单集合上使用map/reduce原语的主要目的是使您的代码简单优雅...

@CurtainDog贡献了一个lambdaj的链接。那个链接可以做到OP想要的事情(虽然没有特别被称为reduce的方法)。但是它说明了我所说的样板代码。请注意,许多高阶操作涉及创建扩展一个或另一个Closure类的类。

(顺便说一下,我认为Lambda.aggregate(...)方法是reduce的lambdaj模拟。)


@user359996 - 你刚刚链接到了Guava javadoc树的根目录。这样做有什么意义? - Stephen C
3
信不信由你,那并不是故意的。这是正确的链接:http://docs.guava-libraries.googlecode.com/git-history/v10.0.1/javadoc/com/google/common/collect/Lists.html#transform(java.util.List,%20com.google.common.base.Function)。 - user359996

5

4

我最近提交了一个问题,在这个问题中我请求/讨论了类似的事情。这就是我实现所需要的。

/**
 * Aggregate the selected values from the supplied {@link Iterable} using
 * the provided selector and aggregator functions.
 * 
 * @param <I>
 *            the element type over which to iterate
 * @param <S>
 *            type of the values to be aggregated
 * @param <A>
 *            type of the aggregated value
 * @param data
 *            elements for aggregation
 * @param selectorFunction
 *            a selector function that extracts the values to be aggregated
 *            from the elements
 * @param aggregatorFunction
 *            function that performs the aggregation on the selected values
 * @return the aggregated value
 */
public static <I, S, A> A aggregate(final Iterable<I> data,
    final Function<I, S> selectorFunction,
    final Function<Iterable<S>, A> aggregatorFunction){
    checkNotNull(aggregatorFunction);
    return aggregatorFunction.apply(
        Iterables.transform(data, selectorFunction)
    );
}

(The选择器函数可以从要查询的对象中提取聚合值,但在许多情况下,它将是Functions.identity(),即对象本身被聚合)
这不是一个经典的折叠,但它需要一个Function, X>来完成工作。但由于实际代码只有一行,我选择请求一些标准的聚合函数(我会把它们放在一个名为Aggregators、AggregatorFunctions甚至Functions.Aggregators的类中):
/** A Function that returns the average length of the Strings in an Iterable. */
public static Function<Iterable<String>,Integer> averageLength()

/** A Function that returns a BigDecimal that corresponds to the average
    of all numeric values passed from the iterable. */
public static Function<Iterable<? extends Number>,BigDecimal> averageOfFloats()

/** A Function that returns a BigInteger that corresponds to the average
    of all numeric values passed from the iterable. */
public static Function<Iterable<? extends Number>,BigInteger> averageOfIntegers()

/** A Function that returns the length of the longest String in an Iterable. */    
public static Function<Iterable<String>,Integer> maxLength()

/** A Function that returns the length of the shortest String in an Iterable. */
public static Function<Iterable<String>,Integer> minLength()

/** A Function that returns a BigDecimal that corresponds to the sum of all
    numeric values passed from the iterable. */
public static Function<Iterable<? extends Number>,BigDecimal> sumOfFloats()

/** A Function that returns a BigInteger that corresponds to the integer sum
    of all numeric values passed from the iterable. */
public static Function<Iterable<? extends Number>,BigInteger> sumOfIntegers()

您可以在问题中看到我的示例实现。

这样,您就可以做出像这样的事情:

int[] numbers = { 1, 5, 6, 9, 11111, 54764576, 425623 };
int sum = Aggregators.sumOfIntegers().apply(Ints.asList(numbers)).intValue();

我知道这不是你要求的内容,但在很多情况下,这会让生活更轻松,并且与你的请求有重叠之处(即使方法不同)。


4
Jedi有一个reduce操作。Jedi还通过使用注释为您生成函数对象来帮助减少样板代码。请参见这些示例

4

Guava提供了 transform(映射)功能。但好像缺少reduce(归纳)功能?


1
我已经开发了一个库,可以在标准的J2SE中进行map/filter/reduce操作。 抱歉它是用法语编写的,但是通过谷歌翻译您可以阅读它: http://caron-yann.developpez.com/tutoriels/java/fonction-object-design-pattern-attendant-closures-java-8/ 您可以像这样使用它:
int sum = dogs.filter(new Predicate<Arguments2<Dog, Integer>>() {

    @Override
    public Boolean invoke(Arguments2<Dog, Integer> arguments) {
        // filter on male
        return arguments.getArgument1().getGender() == Dog.Gender.MALE;
    }
}).<Integer>map(new Function<Integer, Arguments2<Dog, Integer>>() {

    @Override
    public Integer invoke(Arguments2<Dog, Integer> arguments) {
        // get ages
        return arguments.getArgument1().getAge();
    }
}).reduce(new Function<Integer, Arguments2<Integer, Integer>>() {

    @Override
    public Integer invoke(Arguments2<Integer, Integer> arguments) {
        // sum âges
        return arguments.getArgument1() + arguments.getArgument2();
    }
});

System.out.println("Le cumul de l'âge des mâles est de : " + sum + " ans");

享受这个帮助。

0
使用Totally Lazy,它实现了所有这些功能甚至更多。基本上是从Clojure中复制了整个函数式方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接