Ответ 1
Как вы думаете, более элегантно? Простой старый цикл for:
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)
EDIT:
Попробовав код в Eclipse, я обнаружил, что мне нужно добавить оператор return null
в eatFunction
, потому что 1) Void
не совпадает с void
и 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);