6年も前は、リストを比較して処理するのに、ブログ投稿したことを考えてた
http://oboe2uran.hatenablog.com/entry/2010/07/01/121003http://oboe2uran.hatenablog.com/entry/2010/07/01/121003
http://oboe2uran.hatenablog.com/entry/2010/06/26/132425http://oboe2uran.hatenablog.com/entry/2010/07/01/121003
でも、最近は、以下のように書くことが多くなった。
リスト、alist , blist がある時、
alist.stream().filter(e->!blist.contains(e)).forEach(e->{
});
blist.stream().filter(e->!alist.contains(e)).forEach(e->{
});
alist.stream().filter(e->blist.contains(e)).forEach(e->{
});
でも、これは、filter(Predicate) を3回も注意して記述しなければならないし、contains で問い合わせて効率が
悪そう。
そこで考えたのが、
① リスト要素を等しいと判定する BiFunction
② 各々のリストだけに存在する要素に対する Consumer
③ 両方のリストに存在する要素に対する Consumer
を指定して比較処理を普遍的に実行すること。
import java.util.AbstractMap;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
リストの比較.
public final class ListDiff<T>{
private BiFunction<T, T, Boolean> matchFunction;
private Consumer<T> leftonly;
private Consumer<T> rightonly;
private BiConsumer<T, T> biConsumer;
private ListDiff(BiFunction<T, T, Boolean> matchFunction){
this.matchFunction = matchFunction;
}
public static <T> ListDiff<T> of(BiFunction<T, T, Boolean> matchFunction){
return new ListDiff<>(matchFunction);
}
public void leftOnly(Consumer<T> leftonly){
this.leftonly = leftonly;
}
public void rightOnly(Consumer<T> rightonly){
this.rightonly = rightonly;
}
public void match(BiConsumer<T, T> biConsumer){
this.biConsumer = biConsumer;
}
public void diff(List<T> leftList, List<T> rightList){
if (leftonly != null)
leftList.stream().filter(e->rightList.stream()
.noneMatch(t->matchFunction.apply(t, e))).forEach(leftonly);
if (rightonly != null)
rightList.stream().filter(e->leftList.stream()
.noneMatch(t->matchFunction.apply(t, e))).forEach(rightonly);
if (biConsumer != null)
leftList.stream()
.map(e->new AbstractMap.SimpleEntry<T, T>(e
, rightList.stream().filter(t->matchFunction.apply(t, e)).findFirst().orElse(null))
)
.filter(e->e.getValue() != null).forEach(p->{
biConsumer.accept(p.getKey(), p.getValue());
});
}
}
すると、、
ListDiff<String> listDiff = ListDiff.of((t1, t2)->t1.equals(t2));
listDiff.leftOnly(e->{
});
listDiff.rightOnly(e->{
});
listDiff.match((left, right)->{
});
listDiff.diff(alist, blist);
リスト要素を等しいと判定する記述が複雑で長くなるような要素のリストを比較する場合、
判定する記述は、1回の記述で済ませられるし、
この ListDiff インスタンスを使い回せることができる。