我经常发现自己这样做:
list.stream().min(new Comparator<>() {
@Override
public int compare(E a, E b) {
return Double.compare(f(a),f(b));
}
})
Run Code Online (Sandbox Code Playgroud)
哪里f是计算密集型功能.这需要两倍于f实际需要的评估.我更喜欢
list.stream().mapToDouble(f).min()
Run Code Online (Sandbox Code Playgroud)
但后来我不知道如何获得这个最小值对应的原始元素.
围绕这个的一个丑陋的方法是
class WithF<E>{
private final E e;
private final double fe;
WithF(E e, double fe){
this.e = e;
this.fe = fe;
}
public E getE(){
return e;
}
public double getFE(){
return fe;
}
}
Run Code Online (Sandbox Code Playgroud)
然后
list.stream().map(e -> new WithF<>(e,f(e))).min(Comparator.comparingDouble(WithF::getFE))
Run Code Online (Sandbox Code Playgroud)
使用流API是否有更好的,惯用的方法?
这种变换通常称为施瓦茨变换
实际上,我会WithF用一些额外的位进行概括,并将其重命名以使管道更整洁。
class SchwartzianKV<E, SORTKEY implements Comparable<SORTKEY> >
implements Comparable<SchwartzianKV<E, SORTKEY>> {
public final E e;
public final SORTKEY sortkey;
SchwartzianKV(E e, SORTKEY sortkey){
this.e = e;
this.sortkey = sortkey;
}
public static <E, SORTKEY implements Comparable<SORTKEY>>
Function<E, SchwartzianKV<E, SORTKEY>> transformer( Function<E, SORTKEY> fn ) {
return new Function<E, SchwartzianKV<E,SORTKEY>>() {
@Override SchwartzianKV<E,SORTKEY> apply(E e) {
return new SchwartzianKV<>(e, fn.apply(e));
}
}
}
public int compare(With<E> other) {
return sortkey.compare(other.sortkey);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以将流写为
Optional<E> minValue = list.stream()
.map( SchwartianKV.transformer( e -> f(e) ) )
.min()
.map( kv -> kv.e )
Run Code Online (Sandbox Code Playgroud)
这非常简洁。