前回投稿の
Java 複数要素ソートのおさらい - Oboe吹きプログラマの黙示録
は、どうしてもソート対象の要素が、、、
・要素の数、優先順位 の指定はコーディングに依存が強い、、
・昇順のみ
でした。
list.stream().sorted( Comparator.comparing(Fieldgetter.of(t->"width")) .thenComparing( Comparator.comparing(Fieldgetter.of(t->"height")) ) .thenComparing( Comparator.comparing(Fieldgetter.of(t->"depth")) ) )
これを、動的に指定できるようにしたいところです。
そこで以下のように、Comparator 生成するだけの static メソッドを用意します。
import java.util.Comparator; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.IntStream; import org.yipuran.util.Fieldgetter; /** * DyComparator */ public class DyComparator{ // 昇順のみ public static <T> Comparator<T> of(String...sary){ AtomicReference<Comparator<T>> c = new AtomicReference<>(Comparator.comparing(Fieldgetter.of(u->sary[0]))); IntStream.range(1, sary.length).boxed().forEach(e->{ c.set(c.get().thenComparing(Comparator.comparing(Fieldgetter.of(u->sary[e]))) ); }); return c.get(); } // 昇順、降順指定は、reverse=逆順 を true で指定 public static <T> Comparator<T> of(String[] sary, boolean[] revers){ AtomicReference<Comparator<T>> c = new AtomicReference<>(Comparator.comparing(Fieldgetter.of(u->sary[0]))); if (revers[0]) c.set(c.get().reversed()); IntStream.range(1, sary.length).boxed().forEach(e->{ if (revers[e]) { c.set(c.get().thenComparing(Comparator.comparing(Fieldgetter.of(u->sary[e])).reversed())); }else { c.set(c.get().thenComparing(Comparator.comparing(Fieldgetter.of(u->sary[e]))) ); } }); return c.get(); } }
すると、、
list.stream().sorted( DyComparator.of("width", "height", "depth") ).forEach(e->{
height 要素だけを降順にする場合、、
list.stream().sorted( DyComparator.of(new String[]{ "width", "height", "depth"}, boolean[]{ false, true, false}) ).forEach(e->{