javaで関数型風な機能を色々
まずはタプル。
public class Tuple<F,S> { public final F fst; public final S snd; public Tuple(F _fst, S _snd){ this.fst = _fst; this.snd = _snd; } }
簡単ですね。
次に高階関数。
public interface Predicate<E> { public boolean apply(E arg); } public interface Function<F,T> { public T apply(F arg); }
このようなinterfaceを定義しておいて、以下のような関数を定義します(例はリスト操作)。
public class ListUtils { public static<E> List<E> filter(List<E> list, Predicate<? super E> predicate){ List <E> res = new ArrayList<E>(); for(E element : list){ if(predicate.apply(element)) res.add(element); } return res; } public static<F, T> List<T> map(List<F> list, Function<? super F,T> function){ List<T> res = new ArrayList<T>(); for(F element : list){ res.add(function.apply(element)); } return res; } }
使う側は以下。
public class Main { public static void main(String[] args){ List<Integer> lst = new ArrayList<Integer>(); for(int i = 0; i < 10; i++){ lst.add(i); } System.out.println(lst.toString()); // [0,1,2,3,4,5,6,7,8,9] lst = ListUtils.filter(lst, new Predicate<Integer>(){ public boolean apply(Integer n){ return n % 3 == 0; } }); System.out.println(lst.toString()); // [0,3,6,9] List<String> lst2 = ListUtils.map(lst, new Function<Integer,String>(){ public String apply(Integer n){ return String.valueOf(n*2); } }); System.out.println(lst.toString()); // ["0", "6", "12", "18"] } }
普通にループで書くよりタイプ数増えてる説(無名関数が無いので無名クラスで代用している、型推論が無いという理由)。しかし、filterやmapの方が、生のfor文よりも表現力が低いため、結果コードの可読性は高くなっていると思われます。