Ist es möglich, einen Stream in Java 8 zu werfen?

Lesezeit: 5 Minuten

Benutzer-Avatar
Bild

Ist es möglich, einen Stream in Java 8 zu übertragen? Angenommen, ich habe eine Liste von Objekten, kann ich so etwas tun, um alle zusätzlichen Objekte herauszufiltern:

Stream.of(objects).filter(c -> c instanceof Client)

Wenn ich danach jedoch etwas mit den Clients machen möchte, müsste ich jeden von ihnen casten:

Stream.of(objects).filter(c -> c instanceof Client)
    .map(c -> ((Client) c).getID()).forEach(System.out::println);

Das sieht etwas hässlich aus. Ist es möglich, einen ganzen Stream in einen anderen Typ umzuwandeln? Wie gegossen Stream<Object> zu einem Stream<Client>?

Bitte ignorieren Sie die Tatsache, dass solche Dinge wahrscheinlich schlechtes Design bedeuten würden. Wir machen solche Sachen in meinem Informatikunterricht, also habe ich mich mit den neuen Funktionen von Java 8 befasst und war neugierig, ob das möglich ist.

  • Aus Sicht der Java-Laufzeit sind die beiden Stream-Typen bereits identisch, sodass keine Umwandlung erforderlich ist. Der Trick besteht darin, es am Compiler vorbeizuschmuggeln. (Das heißt, vorausgesetzt, es macht Sinn, dies zu tun.)

    – Heiße Licks

    19. März 2014 um 16:23 Uhr

Benutzer-Avatar
Assyrien

Ich glaube nicht, dass es eine Möglichkeit gibt, das out-of-the-box zu tun. Eine möglicherweise sauberere Lösung wäre:

Stream.of(objects)
    .filter(c -> c instanceof Client)
    .map(c -> (Client) c)
    .map(Client::getID)
    .forEach(System.out::println);

oder, wie in den Kommentaren vorgeschlagen, könnten Sie die verwenden cast -Methode – Ersteres ist möglicherweise einfacher zu lesen:

Stream.of(objects)
    .filter(Client.class::isInstance)
    .map(Client.class::cast)
    .map(Client::getID)
    .forEach(System.out::println);

  • Das ist so ziemlich das, wonach ich gesucht habe. Ich glaube, ich habe übersehen, dass ich es an den Client gesendet habe map würde a zurückgeben Stream<Client>. Vielen Dank!

    – Aussage

    19. März 2014 um 16:35 Uhr


  • +1 interessante neue Wege, obwohl sie riskieren, in Spaghetti-Code einer neuen Generation zu geraten (horizontal, nicht vertikal)

    – Robertmann

    20. März 2014 um 8:44 Uhr

  • @LordOfThePigs Ja, es funktioniert, obwohl ich nicht sicher bin, ob der Code klarer wird. Ich habe die Idee zu meiner Antwort hinzugefügt.

    – Assylias

    22. Juni 2014 um 22:38 Uhr

  • Sie könnten den instanceOf-Filter “vereinfachen” mit: Stream.of(objects).filter(Client.class::isInstance).[...]

    – Nikolaus Labrot

    26. November 2014 um 21:43 Uhr


  • @T3rm1 wenn man mit Rohtypen arbeitet, wird vieles schwieriger…

    – Assylias

    2. Februar 2021 um 17:51 Uhr

Benutzer-Avatar
Brandon

In Anlehnung an ggovans Antwort mache ich das wie folgt:

/**
 * Provides various high-order functions.
 */
public final class F {
    /**
     * When the returned {@code Function} is passed as an argument to
     * {@link Stream#flatMap}, the result is a stream of instances of
     * {@code cls}.
     */
    public static <E> Function<Object, Stream<E>> instancesOf(Class<E> cls) {
        return o -> cls.isInstance(o)
                ? Stream.of(cls.cast(o))
                : Stream.empty();
    }
}

Verwenden dieser Hilfsfunktion:

Stream.of(objects).flatMap(F.instancesOf(Client.class))
        .map(Client::getId)
        .forEach(System.out::println);

Spät zur Party, aber ich denke, es ist eine nützliche Antwort.

flatMap wäre der kürzeste Weg.

Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())

Wenn o ist ein Client Erstellen Sie dann einen Stream mit einem einzelnen Element, verwenden Sie andernfalls den leeren Stream. Diese Streams werden dann zu a abgeflacht Stream<Client>.

  • Ich habe versucht, dies zu implementieren, erhielt aber eine Warnung, dass meine Klasse „ungeprüfte oder unsichere Operationen verwendet“ – ist das zu erwarten?

    – aweibell

    10. Dezember 2014 um 12:57 Uhr

  • leider ja. Sollten Sie eine verwenden if/else eher als das ?: Betreiber dann würde es keine Warnung geben. Seien Sie versichert, dass Sie die Warnung sicher unterdrücken können.

    – ggowan

    10. Dezember 2014 um 17:46 Uhr

  • Eigentlich ist das länger als Stream.of(objects).filter(o->o instanceof Client).map(o -> (Client)o) oder auch Stream.of(objects).filter(Client.class::isInstance).map(Client.class::cast).

    – Didier L

    19. Januar 2016 um 16:17 Uhr

Benutzer-Avatar
Rohit Jain

Das sieht etwas hässlich aus. Ist es möglich, einen ganzen Stream in einen anderen Typ umzuwandeln? Wie gegossen Stream<Object> zu einem Stream<Client>?

Nein das wäre nicht möglich. Dies ist nicht neu in Java 8. Dies ist spezifisch für Generika. EIN List<Object> ist kein Supertyp von List<String>also kannst du nicht einfach a wirken List<Object> zu einem List<String>.

Ähnlich verhält es sich hier. Du kannst nicht werfen Stream<Object> zu Stream<Client>. Natürlich können Sie es indirekt so übertragen:

Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;

aber das ist nicht sicher und kann zur Laufzeit fehlschlagen. Der eigentliche Grund dafür ist, dass Generika in Java durch Erasure implementiert werden. Es sind also keine Typinformationen darüber verfügbar, um welchen Typ es sich handelt Stream es ist zur Laufzeit. Alles ist gerecht Stream.

BTW, was ist falsch an deinem Ansatz? Sieht gut aus für mich.

Ich habe festgestellt, dass Sie beim Umgang mit einer nicht typisierten Sammlung einer Klasse eine typisierte Sammlung erstellen können

UntypedObjCollection bag = some preGenerics method;
List<Foo> foolist = new ArrayList<>();
bag.stream().forEach(o ->fooList.add((Foo)o));

Es scheint keine Möglichkeit zu geben, Objekt in etwas zu werfen und zu filtern, zuzuordnen usw. in einem Schuss. Die einzige Möglichkeit, Object in eine typisierte Sammlung zu bekommen, ist eine Terminaloperation. Dies führt JDK 17 aus und behandelt module.base-Ausnahmen, wenn weniger granulare Methoden ausprobiert werden.

1352980cookie-checkIst es möglich, einen Stream in Java 8 zu werfen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy