Guava - 如何应用在可迭代对象上返回 Void 的函数

2022-09-04 05:39:14

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

我的用例是:

  • 我有一个对象列表Animal
  • 我想调用每个动物列表的函数eat()

我有一个哪个电话Function<Animal,Void>input.eat();

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

Collections2.transform(animalList,eatFunction);

我不认为这很优雅,因为我不是在寻找转换,而只是在寻找没有任何输出的应用程序。最糟糕的是,它甚至不起作用,因为番石榴的转变正在回归观点。

正常工作的是:

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

但它并不优雅。使用番石榴以功能方式将Void函数应用于可迭代/集合的最佳方法是什么?

编辑


答案 1

您认为哪个更优雅?一个普通的老循环:

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语言。

Scala可能是这种情况的一个很好的选择:

animalList.foreach(animal => animal.eat)

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

animalList.foreach(_.eat)

编辑:

在 Eclipse 中尝试了代码后,我发现我必须将语句添加到 中,因为 1) 与 和 2) 不相同。这比预期的还要丑陋!:)return nulleatFunctionVoidvoid

同样从性能的角度来看,通过使用上面一些复制构造函数来调用惰性函数也毫无意义地分配内存。创建与仅填充 null 的大小相同的 a,只是为了立即进行垃圾回收。ArrayListanimalList

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

答案 2

我只是在寻找同样的东西,并找到了一个Java消费者接口。在你的情况下,它将是:

final Consumer<Animal> action = new Consumer<Animal>() {
    @Override
    public void accept(Animal animal) {
        animal.eat();
    }
};    
...
FluentIterable.from(animals).forEach(action);