Pet*_*ler 23 java collections functional-programming folding
我有一个List,并希望将其减少为单个值(函数式编程术语"折叠",Ruby术语inject),如
Arrays.asList("a", "b", "c") ... fold ... "a,b,c"
Run Code Online (Sandbox Code Playgroud)
由于我感染了函数式编程思想(Scala),我正在寻找一种更简单/更短的编码方式
sb = new StringBuilder
for ... {
append ...
}
sb.toString
Run Code Online (Sandbox Code Playgroud)
Apo*_*isp 13
回答你原来的问题:
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; }
Run Code Online (Sandbox Code Playgroud)
F看起来像这样:
public interface F<A, B> { public B f(A a); }
Run Code Online (Sandbox Code Playgroud)
正如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(",")));
Run Code Online (Sandbox Code Playgroud)
例2:
import static fj.data.List.list;
import static fj.pre.Monoid.stringMonoid;
...
String abc = stringMonoid.join(list("a", "b", "c"), ",");
Run Code Online (Sandbox Code Playgroud)
例3:
import static fj.data.Stream.fromString;
import static fj.data.Stream.asString;
...
String abc = asString(fromString("abc").intersperse(','));
Run Code Online (Sandbox Code Playgroud)
Tet*_*Oni 10
特定
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();
}
Run Code Online (Sandbox Code Playgroud)
然后使用看起来像
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(); }
}
);
Run Code Online (Sandbox Code Playgroud)
如果你想将一些功能方面应用于普通的旧Java,而不需要切换语言,尽管你可以使用 LamdaJ,fork-join(166y)和google-collections是帮助你添加语法糖的库.
在google-collections的帮助下,您可以使用Joiner类:
Joiner.on(",").join("a", "b", "c")
Run Code Online (Sandbox Code Playgroud)
Joiner.on(",") 是一个不可变对象,因此您可以自由共享它(例如作为常量).
您还可以配置Joiner.on(", ").useForNull("nil");或处理空值处理Joiner.on(", ").skipNulls().
为了避免在生成大字符串时分配大字符串,可以使用它通过Appendable接口或StringBuilder类附加到现有的Streams,StringBuilders等:
Joiner.on(",").appendTo(someOutputStream, "a", "b", "c");
Run Code Online (Sandbox Code Playgroud)
在写出地图时,您需要两个不同的分隔符来表示键和值之间的分隔和分隔:
Joiner.on(", ").withKeyValueSeparator(":")
.join(ImmutableMap.of(
"today", "monday"
, "tomorrow", "tuesday"))
Run Code Online (Sandbox Code Playgroud)
你正在寻找的是一个字符串"join"函数,遗憾的是,Java没有.您将不得不滚动自己的连接功能,这不应该太难.
编辑: org.apache.commons.lang.StringUtils似乎有许多有用的字符串函数(包括join).
您正在寻找的是join()Java自8.0以来的字符串方法.尝试以下方法之一.
静态方法String#join(delimiter, elements):
Collection<String> source = Arrays.asList("a", "b", "c");
String result = String.join(",", source);
Run Code Online (Sandbox Code Playgroud)Stream接口支持折叠操作,与Scala的foldLeft功能非常相似.看一下下面的连接收集器:
Collection<String> source = Arrays.asList("a", "b", "c");
String result = source.stream().collect(Collectors.joining(","));
Run Code Online (Sandbox Code Playgroud)
您可能希望静态导入Collectors.joining以使代码更清晰.
顺便说一下,这个收集器可以应用于任何特定对象的集合:
Collection<Integer> numbers = Arrays.asList(1, 2, 3);
String result = numbers.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
25072 次 |
| 最近记录: |