Java中的可累加和?

时间:2011-01-21 11:37:32

标签: java

是否存在执行此操作的库:

public class Iterables{
    private Iterables() {}

    public static <T> int sum(Iterable<T> iterable, Func<T, Integer> func) {
        int result = 0;
        for (T item : iterable)
            result += func.run(item);
        return result;
    }
}

public interface Func<TInput, TOutput> {
    TOutput run(TInput input);
}

5 个答案:

答案 0 :(得分:10)

基本上有两个有用的库可以帮助解决这个问题。 Google GuavaApache Commons Collections

您要做的基本上是两个操作,首先是映射,然后是缩减。我从来没有在任何程度上使用过Commons Collections,所以我不能告诉你更多关于这一点,但我知道至少在Google Guava中没有支持缩减(或折叠)(见Issue 218)。这不是很难添加自己(未经测试):

interface Function2<A, B> {
  B apply(B b, A a);
}

public class Iterables2 {
    public static <A, B> B reduce(Iterable<A> iterable,
      B initial, Function2<A, B> fun) {
        B b = initial;
        for (A item : iterable)
             b = fun.apply(b, item);
        return b;
    }
}

这样你可以将它与Guavas Iterables.transform()结合起来:

class Summer implements Function2<Integer, Integer> {
    Integer apply(Integer b, Integer a) {
        return b + a;
    }
}

class MyMapper<T> implements Function<T, Integer> {
    Integer apply(T t) {
      // Do stuff
    }
}

然后(假如你已经导入静态相关的类):

reduce(transform(iterable, new MyMapper()), 0, new Summer());

另见this question

答案 1 :(得分:9)

Java不是一个功能性的语言,通常使用普通循环更简单,更快捷。

你可以写点像

List<String> list = /* ... */
int totalLength = Iterables.sum(list, new Func<String, Integer>() {
    public Integer run(String input) {
        return input.length();
    }
});

然而恕我直言,它更简单,更简单。

List<String> list = /* ... */
int totalLength = 0;
for(String s: list) totalLength += s.length();

当闭包在Java中成为标准时,这将改变,但是现在循环通常是最好的方式。

答案 2 :(得分:8)

由于Java 8现在正在收集集合的总和很简单:

collection.stream().reduce(0, Integer::sum)

不幸的是,流不可用于迭代,但总是可以转换。数组更容易:

LongStream.of(1, 2, 3).sum()

答案 3 :(得分:3)

Functional Java有一个sum方法:

http://functionaljava.googlecode.com/svn/artifacts/3.0/javadoc/fj/function/Integers.html#sum%28fj.data.List%29

以下是一个例子:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
ints.add(3);
int sum = Integers.sum(fj.data.List.iterableList(ints));

答案 4 :(得分:3)

你可以简单地使用Lamdaj - 一个库来以伪功能和静态类型的方式操作集合:

sum = Lambda.sum(iterable);

它也可以执行其他类型的聚合,或者您可以添加自己的聚合器:

sum = Lambda.aggregate(seq, new InitializedPairAggregator<Integer>(0) {
    protected Integer aggregate(Integer first, Integer second) {
        return first + second;
    }
});

有关其他示例,请参阅Features