Guava - 如何应用在Iterable上返回Void的函数

时间:2012-09-14 14:44:32

标签: java functional-programming guava

我只是想知道在Void上应用返回Iterable/Collection的函数的最佳方法是什么?

我的用例是:

  • 我有一个Animal个对象
  • 的列表
  • 我想呼叫列表中的每只动物eat()功能

我有Function<Animal,Void>来调用input.eat();

事实证明,当我打电话时:

Collections2.transform(animalList,eatFunction);

我不觉得这很优雅,因为我不是在寻找转换,而只是为了没有任何输出的应用程序。 最糟糕的是,由于Guava转换正在返回视图,因此它甚至无法工作。

可行的方法是:

Lists.newArrayList( Collections2.transform(animalList,eatFunction) );

但它并不优雅。 使用Guava以函数方式将Void函数应用于Iterable / Collection的最佳方法是什么?

修改

2 个答案:

答案 0 :(得分:27)

您认为更优雅的是什么?一个普通的旧循环:

for (Animal animal : animalList)
    animal.eat();

或“通过在功能样式中编写程序操作来弯曲程序语言”疯狂吗?

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

我会投票支持第一个案例。

如果你真的想用函数式编写程序,我建议你换一种JVM语言,而不是对名叫Java的老太太强奸。 :)

对于这种情况,

Scala 可能是一个不错的选择:

animalList.foreach(animal => animal.eat)

甚至是使用_占位符的较短变体:

animalList.foreach(_.eat)

编辑:

在Eclipse中尝试代码之后,我发现我必须将return null语句添加到eatFunction,因为1)Voidvoid不同和2)它是不可实现的。那比预期的更难看! :)

同样从性能的角度来看,使用上面的一些复制构造函数调用惰性函数也毫无意义地分配了内存。创建与ArrayList大小相同但仅填充空值的animalList,以便立即进行垃圾回收。

如果你真的有一个用例要传递一些函数对象并在一些集合上动态应用它们,我会编写自己的函数接口和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);
        }
    }

}

然后您可以类似地定义void(小写)函数:

static final Block<Animal> eatFunction = new Block<Animal>() {
    @Override
    public void apply(Animal animal) {
        animal.eat();
    }
};

并像这样使用它:

FunctionUtils.forEach(animalList, eatFunction);
// or with a static import:
forEach(animalList, eatFunction);

答案 1 :(得分:5)

正如其他人所指出的那样,番石榴团队的观点不允许这样做。如果您正在寻找其他类似仿函数的API,您可以查看Functional Java's EffectJedi's Command classPlay! framework's F.CallbackCommons Collections4's Closure [稍后修改:基于Java 8+ Consumer的接口。