インターフェースを実装するクラスのオブジェクトをストリーミングしています。実装クラスではなく、インターフェースの要素のリストとして収集したいと思います。
これは、Java 16.0.1 のStream#toList
方法では不可能と思われます。たとえば、以下のコードでは、最後のステートメントがコンパイルに失敗します。
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class WhyDodo {
private interface Dodo { }
private static class FancyDodo implements Dodo { }
public static void main(String[] args) {
final List<Dodo> dodos = Stream.of(new FancyDodo()).collect(Collectors.toList());
final List<FancyDodo> fancyDodos = Stream.of(new FancyDodo()).toList();
final List<Dodo> noFancyDodos = Stream.of(new FancyDodo()).toList();
}
}
FancyDodo
からの各要素を明示的に にキャストすることもできますDodo
。ただし、簡潔にするために、 を使用することもできます.collect(Collectors.toList())
。
Java 16 で Stream#toList を使用してクラスのインターフェースのリストを収集できないのはなぜですか?
また、明示的にキャストするよりも良い解決策をお持ちの方がいらっしゃいましたら、ぜひ教えてください :)
ベストアンサー1
.collect(Collectors.toList())
のシグネチャが次のとおりでcollect
あるため機能します:
<R, A> R collect(Collector<? super T, A, R> collector);
重要なのは? super T
つまり、ストリームの型が であっても、toList()
コレクターは として解釈できますCollector<Dodo,?,List<Dodo>
( の結果.collect()
を に割り当てる場合) 。List<Dodo>
Stream<FancyDodo>
一方、の署名はStream
次toList()
のようになります。
List<T> toList()
したがって、これを に対して実行すると がStream<FancyDodo>
得られList<FancyDodo>
、これを変数に割り当てることはできませんList<Dodo>
。
この場合は、stream.collect(Collectors.toList())
の代わりにを使用することをお勧めします。stream.toList()