webentwicklung-frage-antwort-db.com.de

Java 8 - ohne langwierige Collect-Methode

Java 8 Stream API ist sehr nett und ich mag es absolut. Eine Sache, die mir auf die Nerven geht, ist, dass ich in 90% der Fälle Input als Sammlung und Output als Sammlungen haben möchte. Die Folge ist, dass ich die stream()- und collect()-Methode die ganze Zeit aufrufen muss:

collection.stream().filter(p->p.isCorrect()).collect(Collectors.toList());

Gibt es eine Java-API, die es mir erlaubt, den Stream zu überspringen und Sammlungen direkt auszuführen (wie linq in c #?):

collection.filter(p->p.isCorrect)
56
user3364192

Wenn Sie mit Kollektionen arbeiten wollen, ist Guava FluentIterable ein guter Weg!

Beispiel (IDs von 10 ersten VIP-Kunden erhalten):

FluentIterable
       .from(customers)
       .filter(customer -> customer.isVIP())
       .transform(Client::getId)
       .limit(10);
10
Jakub Dziworski

Ja, mit Collection#removeIf(Predicate) :

Entfernt alle Elemente dieser Auflistung, die dem angegebenen Prädikat entsprechen.

Beachten Sie, dass die angegebene Sammlung geändert wird und keine neue zurückgegeben wird. Sie können jedoch eine Kopie der Sammlung erstellen und diese ändern. Beachten Sie auch, dass das Prädikat negiert werden muss, um als Filter zu fungieren:

public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
                                                      Predicate<? super E> filter) {
    List<E> copyList = new ArrayList<>(unfiltered);

    // removeIf takes the negation of filter 
    copyList.removeIf(e -> { return !filter.test(e);});  

    return copyList;
}

Wie @Holger in den Kommentaren vorschlägt, wenn Sie diese Dienstprogrammmethode in Ihrem Code definieren und überall verwenden, um eine gefilterte Auflistung zu erhalten, dann delegieren Sie den Aufruf einfach an die collect-Methode in diesem Dienstprogramm. Ihr Anrufercode wird dann präziser.

public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
                                                      Predicate<? super E> filter) {
   return unfiltered.stream()
                    .filter(filter)
                    .collect(Collectors.toList());
}
42
manouti

Vielleicht möchten Sie StreamEx

StreamEx.of(collection).filter(PClass::isCorrect).toList();

Dies hat den Vorteil, dass es etwas kürzer ist, während die Unveränderlichkeit erhalten bleibt.

17
GuiSim

Streams hatten eine gut definierte Architektur, über die Sie viel lesen können . Vielleicht möchten Sie darüber lesen, bevor Sie diese Straße entlanggehen.

Aber warum nicht eine Sammlung implementieren, die eine ähnliche Stream-Schnittstelle implementiert, die diesen Code für Sie abschließt? 

public class StreamableCollection implements Collection, Stream {
...
}

Dann könnten Sie einige knifflige Annahmen für Ihren Anwendungsfall treffen. Sie können zwar immer noch einen Stream über die Sammlungsschnittstelle öffnen, aber Sie können auch direkt hinein springen und dann innerhalb dieses Bereichs die Öffnung des Streams handhaben, die ich vermute. 

    streamableCollection cs = new streamableCollection();
    cs.filter();
    cs.stream();

Ihre IDE hebt Sie auf, um alles zu implementieren ... übergeben Sie einfach alles an die Standardimplementierungen.

7
TheNorthWes

Wenn Sie eine gefilterte Ansicht benötigen, ohne die ursprüngliche Sammlung zu ändern, ziehen Sie Guavas Collections2.filter() in Betracht.

7
shmosel

Ich denke auch, dass die Stream API gut ist, aber für kurze Operationen ausführlich ist. Ich habe diese Hilfsmittelmethoden in einigen Projekten verwendet:

import Java.util.List;
import Java.util.function.Function;
import Java.util.function.Predicate;
import Java.util.stream.Collectors;
import Java.util.stream.Stream;

public class Functions {

    public static <T,V> List<V> map(final List<T> in, final Function<T, V> function) {
        return in == null ? null : map(in.stream(), function);
    }

    public static <T,V> List<V> map(final Stream<T> in, final Function<T, V> function) {
        return in == null ? null : in
            .map(function)
            .collect(Collectors.toList());
    }

    public static <T> List<T> filter(final List<T> in, final Predicate<T> predicate) {
        return in == null ? null : filter(in.stream(), predicate);
    }

    public static <T> List<T> filter(final Stream<T> in, final Predicate<T> predicate) {
        return in == null ? null : in
            .filter(predicate)
            .collect(Collectors.toList());
    }
}

Dies lässt mich z.

List<String> wrapped = Functions.map(myList, each -> "[" + each + "]");

Normalerweise importiere ich die Methode auch statisch.

6
Rory Hunter

Wenn Sie für die Verwendung einer Drittanbieter-Bibliothek offen sind, können Sie Eclipse Collections verwenden, die über umfangreiche APIs verfügt, die direkt unter Collections verfügbar sind. Ihr Beispiel kann mit Eclipse-Sammlungen wie folgt geschrieben werden.

collection.select(p->p.isCorrect)
collection.select(MyClass::isCorrect)

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.

3
itohro

Ja, es gibt mehrere Bibliotheken, die die Stream-Ausführlichkeit von Java 8 ansprechen. Eine unvollständige Liste:

Meine Vorliebe gilt für JOOL. Ich habe es in meinen letzten Projekten verwendet. Die anderen, die ich kenne, aber ich habe sie nicht wirklich benutzt, daher kann ich Ihnen keinen Eindruck vermitteln.

Ihr Beispiel mit jOOL wäre:

Seq.seq(collection).filter(p->p.isCorrect()).toList();
1
sargue

Sie könnten dies aus der Guavenbibliothek versuchen. Es scheint etwas unübersichtlicher als der Stream-Ansatz.

 ImmutableList.copyOf(Iterables.filter(collection, MyClass::isCorrect));

Siehe Google-Sammlungen (Guava-Bibliotheken): ImmutableSet/List/Map and Filtering für eine Diskussion der Technik.

1
Hank D

Mit cyclops-reagieren haben Sie eine Reihe von Optionen.

Wir können Lazy Extended Collections nutzen

  CollectionX<String> collection = ListX.of("hello","world");
  CollectionX<String> filtered = collection.filter(p->p.isCorrect());

Es gibt Unterstützung für veränderliche, unveränderliche und persistente erweiterte Sammlungen. Funktionsoperationen für Sammlungen sind träge (d. H. Sie verhalten sich wie wiedergabefähige Streams) und werden nur beim ersten Zugriff verwirklicht.

Wir können einen leistungsfähigen erweiterten Stream-Typ verwenden

  ReactiveSeq.fromIterable(collection)
             .filter(p->p.isCorrect())
             .toList();

[Offenlegung Ich bin der Hauptentwickler von Cyclops-React]

0
John McClean