2011-01-21 59 views
12

有沒有做這個庫: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); 
} 

回答

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; 
    } 
} 

這樣,你可以用番石榴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 
    } 
} 

然後(前提是你」 ve導入static'ed相關類):

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

另請參閱this question

+0

你能解決你的例子嗎?我得到'方法適用於(A)函數不適用於fun.apply()行上的參數(B,A)`。 – 2016-04-19 17:43:25

+0

也許吧。可能不會。答案是5歲,只是使用Java 8流:) – 2016-04-20 11:46:00

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中成爲標準時,這將會改變,但現在循環往往是最好的方式。

3

你可以簡單地使用Lamdaj - 庫來操縱集合在一個僞功能和靜態類型方式:

sum = Lambda.sum(iterable); 

它還可以做其他類型的聚集,也可以ADDD你自己的聚合器:

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

其他例子見Features

7

由於Java 8,現在得到了收藏上一筆很簡單:

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

不幸的是流上不可iterables但可以隨時轉換。陣列更容易:

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