Die wichtigste Sache zu verstehen, in Bezug auf diese Frage ist, dass, wenn Sie einen Lambda-Ausdruck an eine bestimmte Bibliothek wie die Stream
API übergeben, alle Bibliothek empfängt eine Implementierung einer funktionalen Schnittstelle, z. eine Instanz von Predicate
. Es hat keine Kenntnis darüber, was diese Implementierung tun wird, und hat daher keine Möglichkeit, Szenarien wie das Filtern sortierter Daten über Vergleiche zu nutzen. Die Stream-Bibliothek weiß einfach nicht, dass der Predicate
einen Vergleich macht.
Eine Implementierung, die eine solche Optimierung durchführt, würde eine Interaktion der JVM, die den Code kennt und versteht, und der Bibliothek, die die Semantik kennt, benötigen. So etwas passiert in der aktuellen Implementierung nicht und ist derzeit weit weg, zumindest so, wie ich es sehen kann.
Wenn die Quelle eine Baum- oder sortierte Liste ist und Sie davon für das Filtern profitieren möchten, müssen Sie vor der Erstellung des Streams APIs verwenden, die auf der Quelle ausgeführt werden. Z.B.nehme an, wir haben eine TreeSet
und wollen es filtern, Artikel in einem bestimmten Bereich zu bekommen, wie
// our made-up source
TreeSet<Integer> tree=IntStream.range(0, 100).boxed()
.collect(Collectors.toCollection(TreeSet::new));
// the naive implementation
tree.stream().filter(i -> i>=65 && i<91).forEach(i->System.out.print((char)i.intValue()));
Wir tun kann stattdessen:
tree.tailSet(65).headSet(91).stream().forEach(i->System.out.print((char)i.intValue()));
, die die sortierte/Baum Natur werden nutzen. Wenn wir stattdessen eine sortierte Liste haben, sagen
List<Integer> list=new ArrayList<>(tree);
die sortierte Art unter Verwendung komplexer ist als die Sammlung selbst nicht weiß, dass sie sortiert ist und bietet keine Operationen, die direkt unter Verwendung von:
int ix=Collections.binarySearch(list, 65);
if(ix<0) ix=~ix;
if(ix>0) list=list.subList(ix, list.size());
ix=Collections.binarySearch(list, 91);
if(ix<0) ix=~ix;
if(ix<list.size()) list=list.subList(0, ix);
list.stream().forEach(i->System.out.print((char)i.intValue()));
Natürlich sind die Stream-Operationen hier nur beispielhaft und Sie brauchen überhaupt keinen Stream, wenn Sie dann nur forEach
...
können Können Sie nicht eine 'Karte>' stattdessen verwenden? –
Keppil
@Keppil Ja danke. Nach Betrachtung denke ich, dass das, was Sie vorschlagen, das effizienteste ist. Jemand anderes hat gerade einen Kommentar gelöscht, der besagt, dass die Sammlung, nach der ich suche, etwas Wissen über die Interna von 'Thing' benötigen würde, also wäre es besser,' Thing.type' über eine Map zu indizieren. – Wernsey