web-dev-qa-db-ja.com

Java 8でストリームをキャストすることはできますか?

Java 8でストリームをキャストすることはできますか?オブジェクトのリストがあるとします。追加のオブジェクトをすべて除外するには、次のようにします。

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

ただし、この後、クライアントで何かをしたい場合は、それぞれをキャストする必要があります。

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

これは少しいようです。ストリーム全体を別のタイプにキャストすることは可能ですか? Stream<Object>Stream<Client>にキャストしたいですか?

このようなことを行うと、おそらく悪い設計を意味するという事実を無視してください。私のコンピューターサイエンスクラスではこのようなことをしているので、Java 8の新機能を検討しており、これが可能かどうか興味がありました。

125
Phiction

すぐに使用できる方法はないと思います。おそらくよりクリーンなソリューションは次のとおりです。

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

または、コメントで示唆されているように、castメソッドを使用できます-前者の方が読みやすいかもしれません:

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

ggovan's answer の線に沿って、次のようにこれを行います。

/**
 * 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();
    }
}

このヘルパー関数の使用:

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

パーティーに遅れて、しかし私はそれが有用な答えだと思います。

flatMapが最短の方法です。

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

oClientの場合、単一の要素でStreamを作成し、そうでない場合は空のストリームを使用します。これらのストリームは、その後Stream<Client>にフラット化されます。

9
ggovan

これは少しいようです。ストリーム全体を別のタイプにキャストすることは可能ですか? Stream<Object>Stream<Client>にキャストしたいですか?

いいえ、それは不可能です。これはJava 8の新機能ではありません。これはジェネリックに固有です。 List<Object>List<String>のスーパータイプではないため、List<Object>List<String>にキャストすることはできません。

ここでも同様の問題があります。 Stream<Object>Stream<Client>にキャストできません。もちろん、次のように間接的にキャストできます。

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

しかし、それは安全ではなく、実行時に失敗する可能性があります。この理由は、Javaのジェネリックが消去を使用して実装されているためです。そのため、実行時のStreamのタイプに関するタイプ情報はありません。すべてがStreamです。

ところで、あなたのアプローチの何が問題になっていますか?私には問題ありません。

5
Rohit Jain