Reputation: 5504
How can I do the following (this doesn't compile):
<T> List<T> getElementsOf() {
return list.stream()
.filter(x -> x instanceof T)
.map(x -> (T) x)
.collect(toList());
}
What would be example of usage? Ideally, it should be like obj.<Derived>getElementsOf()
.
Upvotes: 10
Views: 8073
Reputation: 23242
Note that generic type information is erased at runtime, so to make that even clearer I exchanged the T
with Object
. Actually the Object
wouldn't be there too, but I kept it to make it clearer, where the T
was:
List<Object> getElementsOf() {
return list.stream()
.filter(x -> x instanceof Object) // this is legal, as Object is an actual type, T isn't
.map(x -> (Object) x)
.collect(toList());
}
As you can see now, this doesn't make much sense. There is no way to infer the type without passing it as parameter. You already got the solution yourself and I only wanted to make it clearer also for others not so familiar with generics.
<T> List<T> getElementsOf(Class<T> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(toList());
}
If we exchange T
now with Object, we will see, that the type is still here and so you can cast it appropriately:
List getElementsOf(Class type) {
return list.stream()
.filter(type::isInstance) // is type an Object? is it Long? we don't mind... we passed it and we deliver it
.map(type::cast) // actually this isn't really needed, if you have a return type of List (as you already filtered for the types you want)
.collect(toList());
}
Note also, that with that method you will never get null
values when supplying a type. isInstance
will return false
in such a case.
Upvotes: 0
Reputation: 271050
Although the other answer pretty much does the job, here's a better one:
<T> List<T> getElementsOf(Class<T> clazz) {
return list.stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.collect(toList());
}
Notice that the clazz::isInstance
thingy. Instead of comparing the two classes, it uses the isInstance
method. According to the docs, this is equivalent to instanceof
, which is what you wanted in the first place.
This method is the dynamic equivalent of the Java language instanceof operator.
Upvotes: 25
Reputation: 5504
I got the following:
<T> List<T> getChildrenOf(Class<T> clazz) {
return children.stream()
.filter(node -> node.getClass() == clazz)
.map(node -> clazz.<T>cast(node))
.collect(toList());
}
List<Mesh> nameNodes = b.getChildrenOf(Mesh.class);
Upvotes: 1