何がよりエレガントだと思いますか?昔ながらの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)
編集:
Eclipseでコードを試した後、1)はと同じではなく、2)インスタンス化できないため、return null
ステートメントをに追加する必要があることがわかりました。それは予想よりもさらに醜いです!:)eatFunction
Void
void
また、パフォーマンスの観点から、上記のようなコピーコンストラクターを使用してレイジー関数を呼び出すと、メモリが無意味に割り当てられます。nullのみで埋められた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);