如何在 Java 中实现列表折叠

我有一个列表,并希望将其简化为单个值(函数式编程术语“fold”,Ruby术语),例如inject

Arrays.asList("a", "b", "c") ... fold ... "a,b,c"

由于我感染了函数式编程思想(Scala),我正在寻找一种比现在更简单/更短的编码方式。

sb = new StringBuilder
for ... {
  append ...
}
sb.toString

答案 1

要回答您的原始问题:

public static <A, B> A fold(F<A, F<B, A>> f, A z, Iterable<B> xs)
{ A p = z;
  for (B x : xs)
    p = f.f(p).f(x);
  return p; }

其中 F 如下所示:

public interface F<A, B> { public B f(A a); }

正如dfa所建议的,Functional Java已经实现了这一点,甚至更多。

示例 1:

import fj.F;
import static fj.data.List.list;
import static fj.pre.Monoid.stringMonoid;
import static fj.Function.flip;
import static fj.Function.compose;

F<String, F<String, String>> sum = stringMonoid.sum();
String abc = list("a", "b", "c").foldLeft1(compose(sum, flip(sum).f(",")));

示例 2:

import static fj.data.List.list;
import static fj.pre.Monoid.stringMonoid;
...
String abc = stringMonoid.join(list("a", "b", "c"), ",");

示例 3:

import static fj.data.Stream.fromString;
import static fj.data.Stream.asString;
...
String abc = asString(fromString("abc").intersperse(','));

答案 2

鉴于

public static <T,Y> Y fold(Collection<? extends T> list, Injector<T,Y> filter){
  for (T item : list){
    filter.accept(item);
  }
  return filter.getResult();
}

public interface Injector<T,Y>{
  public void accept(T item);
  public Y getResult();
}

然后用法只是看起来像

fold(myArray, new Injector<String,String>(){
  private StringBuilder sb = new StringBuilder();
  public void Accept(String item){ sb.append(item); }
  public String getResult() { return sb.toString(); }
}
);