C
Lassen Sie eine Klasse definiert werden (teilweise) durchWie binär Suche auf einem Feld eines Elemente der Liste
private static class C {
private final int x;
// lots more fields be here
public C(int x, /* lots more arguments here */) {
this.x = x;
// lots more fields initialized here
}
public int getX(){
return x;
}
}
und lassen cs
ein List<C>
sein RandomAccess
Implementierung und sortiert auf C.getX()
.
Was wäre der Standardansatz für eine binäre Suche in cs
für x1
unter C.getX()
? (Mit anderen Worten vorgeben, dass jedes Element c
durch c.getX()
ersetzt wird und dann suchen wir nach x1
unter diesen Zahlen.)
Collections.binarySearch(
cs,
new C(x1,/* dummy arguments */),
(a,b) -> Integer.compare(a.getX(),b.getX())
);
hat den Nachteil, dass es Bau eines neuen C
erfordert (die erfordern viele Dummy-Argumente und Wissen über C
).
hat den Nachteil, dass es eine ganze neue Liste erstellt und vermutlich O (n) ist.
Gibt es eine Möglichkeit, im Stream direkt zu suchen, ohne es zu sammeln? Oder vielleicht eine andere Möglichkeit, die ursprüngliche Liste zu durchsuchen, ohne ein Dummy-Objekt konstruieren zu müssen?
In Ermangelung eines besseren Ansatz, würde ich dies tun:
public class MappedView<T,E> extends AbstractList<E> {
public static <T,E> MappedView<T,E> of(List<T> backingList, Function<T,E> f){
return new MappedView<>(backingList, f);
}
private final List<T> backingList;
private final Function<T,E> f;
private MappedView(List<T> backingList, Function<T,E> f){
this.f = f;
this.backingList = backingList;
}
@Override
public E get(int i) {
return f.apply(backingList.get(i));
}
@Override
public int size() {
return backingList.size();
}
}
und dann
Collections.binarySearch(
MappedView.of(cs, c -> c.getX()),
x1
);
Der binäre Suchalgorithmus erfordert Kenntnisse über die Größe der Sammlung, die nicht einfach in einem Stream erfasst werden kann. Sie brauchen also eine Sammlung oder ein Array. Ich glaube nicht, dass es eine eingebaute Methode im JDK gibt, die das Mapping während der Binärsuche erlaubt. Ihre vorgeschlagene Vorgehensweise (mit MappedView) scheint also eine vernünftige und effiziente Lösung zu sein. Es sei denn, Sie können etwas wie "C.getInstance (x1)" einführen, um ein "dummy" C-Objekt zu erzeugen? – assylias
Sie sollten 'RandomAccess' auch auf Ihrer' MappedView' implementieren, oder es funktioniert möglicherweise nicht effektiv mit 'Collections.binarySearch'. Alternativ können Sie 'Lists.transform' aus Guava verwenden, was Ihnen das alles ermöglicht. –
@LouisWasserman Das ist wahrscheinlich eine elementare Frage, aber wie würde ich sicherstellen, dass das Argument 'backingList' sowohl' List' als auch 'RandomAccess' implementiert? Muss ich dafür eine neue Schnittstelle erstellen? (Oder gibt es schon so etwas wie "RandomAccessList"?) – Museful