Seb*_*ber 13 java functional-programming guava
我只是想知道应用返回函数的最佳方法Void
是Iterable/Collection
什么?
我的用例是:
Animal
对象列表eat()
功能我有一个Function<Animal,Void>
电话input.eat();
事实证明,当我打电话时:
Collections2.transform(animalList,eatFunction);
Run Code Online (Sandbox Code Playgroud)
我不觉得这很优雅,因为我不是在寻找转换,而只是为了没有任何输出的应用程序.最糟糕的是,由于Guava转换正在返回视图,因此它甚至无法工作.
什么工作正常是:
Lists.newArrayList( Collections2.transform(animalList,eatFunction) );
Run Code Online (Sandbox Code Playgroud)
但它并不优雅.使用Guava以函数方式将Void函数应用于Iterable/Collection的最佳方法是什么?
编辑:
Nat*_*tix 27
你觉得什么更优雅?一个普通的旧循环:
for (Animal animal : animalList)
animal.eat();
Run Code Online (Sandbox Code Playgroud)
或者"通过编写功能风格的程序操作来弯曲程序性语言"的疯狂?
static final Function<Animal, Void> eatFunction = new Function<Animal, Void>() {
@Override
public Void apply(Animal animal) {
animal.eat();
return null; // ugly as hell, but necessary to compile
}
}
Lists.newArrayList(Collections2.transform(animalList, eatFunction));
Run Code Online (Sandbox Code Playgroud)
我会投票给第一个案子.
如果您真的想以函数式编写程序,我建议您切换到另一种JVM语言,而不是对名为Java的老太太强奸.:)
对于这种情况,Scala可能是一个很好的选择:
animalList.foreach(animal => animal.eat)
Run Code Online (Sandbox Code Playgroud)
甚至是使用_
占位符的较短变体:
animalList.foreach(_.eat)
Run Code Online (Sandbox Code Playgroud)
在Eclipse中尝试代码之后,我发现我必须将return null
语句添加到eatFunction
,因为1)Void
不同于void
和2)它是不可实现的.那比预期的更难看!:)
同样从性能的角度来看,通过使用上面的一些复制构造函数来调用惰性函数也毫无意义地分配内存.一个ArrayList
为大小相同的animalList
用null不仅填补创建只是要立即垃圾收集.
如果你真的有一个用例要传递一些函数对象并在一些集合上动态应用它们,我会编写自己的函数接口和foreach方法:
public interface Block<T> {
void apply(T input);
}
public class FunctionUtils {
public static <T> void forEach(Iterable<? extends T> iterable,
Block<? super T> block) {
for (T element : iterable) {
block.apply(element);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以类似地定义一个void
(小写)函数:
static final Block<Animal> eatFunction = new Block<Animal>() {
@Override
public void apply(Animal animal) {
animal.eat();
}
};
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
FunctionUtils.forEach(animalList, eatFunction);
// or with a static import:
forEach(animalList, eatFunction);
Run Code Online (Sandbox Code Playgroud)
我只是在寻找相同的东西,并找到了一个Java Consumer界面.在你的情况下,它将是:
final Consumer<Animal> action = new Consumer<Animal>() {
@Override
public void accept(Animal animal) {
animal.eat();
}
};
...
FluentIterable.from(animals).forEach(action);
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,番石榴团队的观点不允许这样做.如果您正在寻找其他类似仿函数的API来做您想做的事情,您可以查看Functional JavaEffect
,或者Jedi的Command
课程,或者Play!框架F.Callback
,或Commons Collections4的Closure
[后编辑:]或基于Java 8+Consumer
的接口.