I'm streaming objects of a class implementing an interface. I'd like to collect them as a list of elements of the interface, rather than the implementing class.
This seems impossible with Java 16.0.1's Stream#toList
method. For example in the code below, the last statement will fail to compile.
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();
}
}
We could explicitly cast each element from FancyDodo
to Dodo
. But at least for brevity, we could just as well use .collect(Collectors.toList())
.
Why can't I use Stream#toList to collect a list of a class' interface in Java 16?
And if anyone has a better solution than explicitly casting, I'd be happy to hear as well :)
Make sure your browser is up-to-date, too - head to the settings menu and check for any updates, then install them and restart your browser. Browser extensions can create slowdown on web pages, including for video streaming services.
There may be tiny problems with the programs or processes on your operating system that stop your Steam client from opening. Or maybe the state or the cache of your computer are interfering with your client. You can try restarting your computer to get rid of these issues. Then check to see if you can open Steam.
Your channel's live streaming ability will be automatically turned off or suspended for any of the following reasons: Your channel got a Community Guidelines strike. Your live stream or archived live stream is blocked globally. Your live stream or archived live stream gets a copyright takedown.
Media Streaming is linked to Windows Search Indexing and can be affected by it. If you have disabled Windows Search Indexing for some reason, you have to re-enable it before Media Streaming will start working. Follow these easy steps to enable Windows Search Indexing:
Solution Re: Can't access Microsoft Stream Hi, usually the best way to get specific technical support is opening a service request, so the particulars can be investigated, this can be done online or via phone, this is aimed at administrators typically who manage Office 365 for their organisation:
Microsoft Stream supports Microsoft Edge and the current versions of Chrome and Safari. What is an encoder? Simply put, an encoder compresses audio and video from various inputs and sends that output to a streaming service, such as Microsoft Stream. Typically, there are hardware, software and mobile apps that you can use.
CANT PLAY VIDEO STREAM IT KEEPS TELLING ME Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file. This thread is locked. You can follow the question or vote as helpful, but you cannot reply to this thread.
.collect(Collectors.toList())
works because the signature of collect
is:
<R, A> R collect(Collector<? super T, A, R> collector);
the important part being ? super T
which means the toList()
collector can be interpreted as Collector<Dodo,?,List<Dodo>
(when you assign the result of .collect()
to a List<Dodo>
) even though the type of your stream is Stream<FancyDodo>
.
On the other hand, the signature of Stream
's toList()
is:
List<T> toList()
so if you execute it for a Stream<FancyDodo>
, you'll get a List<FancyDodo>
, which can't be assigned to a List<Dodo>
variable.
I suggest you simply use stream.collect(Collectors.toList())
instead of stream.toList()
in this case.
Because Stream.toList
is declared to return a List<T>
:
default List<T> toList() { ... }
where T
is the element type of the stream. I can't really think of an alternative way of declaring toList
so that it can return your desired type of list. The best you can do is to accept a List<? super T>
as argument, and add the stream elements to it, but that kind of goes against the "aesthetics" of streams - the whole point of this is to be declarative and have little state.
One way you can rewrite your code to make toList
return a list of your desired type, is to specify the type of T
manually. Right now T
is inferred to be FancyDodo
due to Stream.of(new FancyDodo())
, but you can force T
to be Dodo
if you want:
Stream.<Dodo>of(new FancyDodo()).toList();
Now T
is Dodo
, toList
will return a List<Dodo>
.
The best you can do is to accept a
List<? super T>
as argument, and add the stream elements to it
Actually, this is kind of what Collector
is doing. Notice how collect
accepts a Collector<? super T, DoesntMatter, R>
, and returns R
. That contravariant ? super T
is what enables you to use a toList
collector like that. Note also that R
is a generic parameter of collect
, which means that you get to decide what collect
returns, as long as you can provide a collector that collects ? super T
to R
.
Generic type argument resolution happens one method call at a time.
Stream.of(new FancyDodo())
will always resolved T
to FancyDodo
, so will always result in a Stream<FancyDodo>
.
toList()
doesn't resolve T
, it just uses the already-established T
, so the result is always List<FancyDodo>
, and List<FancyDodo>
is not compatible with List<Dodo>
. See: "Is List<Dog>
a subclass of List<Animal>
? Why are Java generics not implicitly polymorphic?"
collect(Collectors.toList())
has a different T
in the Collectors.toList()
, that can resolve differently from the T
of the Stream
. The compiler resolves that T
as Dodo
, because of the desired return type of List<Dodo>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With