Gibt es einen Grund dafür?
Lists.transform()
aber nein
Lists.filter()
?
Wie filtere ich eine Liste richtig? ich könnte benutzen
new ArrayList(Collection2.filter())
Natürlich, aber auf diese Weise kann nicht garantiert werden, dass meine Bestellung gleich bleibt, wenn ich das richtig verstehe.
List.newArrayList(Iterables.filter(...))
sagenLists.newArrayList(Iterables.filter(...))
.Antworten:
Es wurde nicht implementiert, da es eine gefährliche große Anzahl langsamer Methoden wie #get (Index) in der zurückgegebenen Listenansicht (die zu Leistungsfehlern führen) aufdecken würde. Und ListIterator wäre auch ein Problem bei der Implementierung (obwohl ich vor Jahren einen Patch eingereicht habe, um dies zu behandeln).
Da indizierte Methoden in der gefilterten Listenansicht nicht effizient sein können, ist es besser, nur eine gefilterte Iterable zu verwenden, die sie nicht hat.
quelle
filter
bedeutet konsequent eine Ansicht (zusammen mit dem Verhalten , das impliziert) , ob dasIterables.filter
,Sets.filter
usw. DaIterables.filter
verbindet sich leicht mitcopyOf
auf eine beliebigeImmutableCollection
, ich dieses Design Trade-off gut finden (vs mit zusätzlichen Methoden und Namen kommen, wiefilteredCopy
oder Dingsbums , für Kombinationen einfacher Dienstprogramme).Sie können verwenden
Iterables.filter
, die definitiv die Bestellung beibehalten wird.Beachten Sie, dass Sie beim Erstellen einer neuen Liste die Elemente kopieren (natürlich nur Referenzen), sodass keine Live-Ansicht der ursprünglichen Liste angezeigt wird. Das Erstellen einer Ansicht wäre ziemlich schwierig - bedenken Sie diese Situation:
Das müsste über die gesamte ursprüngliche Liste iterieren und den Filter auf alles anwenden. Ich nehme an, es könnte erforderlich sein, dass sich die Prädikatübereinstimmung während der Lebensdauer der Ansicht nicht geändert hat, aber das wäre nicht ganz zufriedenstellend.
(Dies ist nur eine Vermutung, wohlgemerkt. Vielleicht mischt sich einer der Guava-Betreuer mit dem wahren Grund ein :)
quelle
Collections2.filter.iterator
ruft nur anIterables.filter
, das Ergebnis ist also das gleiche.Iterables.filter
Version nur aus Gründen der Klarheit verwenden.view.size()
späteren Code :)Das ist nicht wahr.
Collections2.filter()
ist eine träge evaluierte Funktion - sie filtert Ihre Sammlung erst, wenn Sie auf die gefilterte Version zugreifen. Wenn Sie beispielsweise über die gefilterte Version iterieren, werden die gefilterten Elemente in derselben Reihenfolge wie Ihre ursprüngliche Sammlung aus dem Iterator entfernt (abzüglich der offensichtlich herausgefilterten).Vielleicht haben Sie gedacht, dass es die Filterung im Voraus durchführt und dann die Ergebnisse in eine willkürliche, ungeordnete Sammlung irgendeiner Form speichert - das tut es nicht.
Also , wenn Sie die Ausgabe verwenden ,
Collections2.filter()
als die Eingabe in eine neue Liste, dann wird Ihre ursprüngliche Reihenfolge wird beibehalten.Mit statischen Importen (und der
Lists.newArrayList
Funktion) wird es ziemlich prägnant:Beachten Sie, dass während
Collections2.filter
nicht eifrig Iterierte über die zugrunde liegende Auflistung,Lists.newArrayList
wird - es werden alle Elemente des gefilterten Sammlung extrahieren und kopieren Sie sie in eine neueArrayList
.quelle
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
oder dh.List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
Wie von Jon erwähnt, können Sie verwenden
Iterables.filter(..)
oderCollections2.filter(..)
und wenn Sie keine Live-Ansicht benötigen, können Sie verwendenImmutableList.copyOf(Iterables.filter(..))
oderLists.newArrayList( Iterables.filter(..))
und ja, die Bestellung wird beibehalten.Wenn Sie wirklich daran interessiert sind, warum Teil, können Sie https://github.com/google/guava/issues/505 für weitere Details besuchen .
quelle
Zusammenfassend können Sie einen generischen Wrapper zum Filtern von Listen erstellen:
quelle