Java过滤器列表到泛型类型T.

时间:2016-12-06 06:54:44

标签: java

如何执行以下操作(此操作无法编译):

<T> List<T> getElementsOf() {
    return list.stream()
            .filter(x -> x instanceof T)
            .map(x -> (T) x)
            .collect(toList());
}

用法的例子是什么?理想情况下,它应该像obj.<Derived>getElementsOf()

3 个答案:

答案 0 :(得分:10)

虽然另一个答案几乎完成了这项工作,但这里更好:

<T> List<T> getElementsOf(Class<T> clazz) {
    return list.stream()
            .filter(clazz::isInstance)
            .map(clazz::cast)
            .collect(toList());
}

请注意clazz::isInstance件事。它使用isInstance方法,而不是比较两个类。根据文档,这相当于instanceof,这是你想要的第一个。

  

此方法是Java语言instanceof运算符的动态等价物。

答案 1 :(得分:1)

我得到了以下内容:

<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);

答案 2 :(得分:0)

请注意,泛型类型信息会在运行时被删除,因此为了更清楚,我将TObject进行了交换。实际上Object也不会存在,但我保持它更清晰,T所在的地方:

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

正如您现在所看到的,这没有多大意义。如果不将其作为参数传递,则无法推断出类型。您已经自己获得了解决方案,我只想让那些不熟悉泛型的人更清楚。

<T> List<T> getElementsOf(Class<T> type) {
    return list.stream()
               .filter(type::isInstance)
               .map(type::cast)
               .collect(toList());
}

如果我们现在用Object交换T,我们会看到类型仍在这里,所以你可以适当地投射它:

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

另请注意,使用该方法,在提供类型时,您永远不会获得null值。在这种情况下,isInstance将返回false