如何通过实例获取列表的所有元素?
How to get all elements of a list by instance?
如何通过实例获取列表的所有元素?
我有一个列表,可以包含任何 class 接口实现 Foo
:
interface Foo;
class Bar implements Foo;
我想使用 java8 stream
api 提供一种实用方法来提取特定 class 类型的所有元素:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return (List<T>) list.stream().filter(entry -> type.isInstance(entry)).collect(Collectors.toList());
}
使用:
List<Foo> list;
List<Bar> bars = Util.getFromList(list, Bar.class);
结果:有效,但由于 (List<T>)
的 unchecked cast
,我必须添加 @SuppressWarnings
。我怎样才能避免这种情况?
由于list
和type
不是同一类型而是继承层次关系,您可能会添加另一个类似于以下的类型参数:
public static <T extends Foo, S extends T> List<T> getFromList(List<T> list, Class<S> type) {
return list.stream().filter(type::isInstance).collect(Collectors.toList());
}
这似乎在没有警告的情况下工作:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return list.stream()
.filter(entry -> type.isInstance(entry))
.map(entry->type.cast(entry))
.collect(Collectors.toList());
}
测试用数字替换 Foo 和整数替换 Bar :
public static <T extends Number> List<T> getFromList(List<Number> list, Class<T> type) {
return list.stream().filter(entry -> type.isInstance(entry)).map(entry->type.cast(entry)).collect(Collectors.toList());
}
public static void main(String[] args)
{
List<Number> list = new ArrayList<>();
list.add(5);
list.add(3.4);
list.add(7);
List<Integer> bars = getFromList(list, Integer.class);
System.out.println(bars);
}
输出:
[5, 7]
引入另一个扩展 S
的类型参数是正确的,但是,为了使结果为 List<S>
,而不是 List<T>
,您必须 .map()
将 type::isInstance
谓词传递给 S
.
的条目
public static <T extends Foo, S extends T> List<S> getFromList(List<T> list, Class<S> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}
正如 @Eran 所建议的,这甚至可以简化为仅使用一种类型参数:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}
如何通过实例获取列表的所有元素?
我有一个列表,可以包含任何 class 接口实现 Foo
:
interface Foo;
class Bar implements Foo;
我想使用 java8 stream
api 提供一种实用方法来提取特定 class 类型的所有元素:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return (List<T>) list.stream().filter(entry -> type.isInstance(entry)).collect(Collectors.toList());
}
使用:
List<Foo> list;
List<Bar> bars = Util.getFromList(list, Bar.class);
结果:有效,但由于 (List<T>)
的 unchecked cast
,我必须添加 @SuppressWarnings
。我怎样才能避免这种情况?
由于list
和type
不是同一类型而是继承层次关系,您可能会添加另一个类似于以下的类型参数:
public static <T extends Foo, S extends T> List<T> getFromList(List<T> list, Class<S> type) {
return list.stream().filter(type::isInstance).collect(Collectors.toList());
}
这似乎在没有警告的情况下工作:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return list.stream()
.filter(entry -> type.isInstance(entry))
.map(entry->type.cast(entry))
.collect(Collectors.toList());
}
测试用数字替换 Foo 和整数替换 Bar :
public static <T extends Number> List<T> getFromList(List<Number> list, Class<T> type) {
return list.stream().filter(entry -> type.isInstance(entry)).map(entry->type.cast(entry)).collect(Collectors.toList());
}
public static void main(String[] args)
{
List<Number> list = new ArrayList<>();
list.add(5);
list.add(3.4);
list.add(7);
List<Integer> bars = getFromList(list, Integer.class);
System.out.println(bars);
}
输出:
[5, 7]
引入另一个扩展 S
的类型参数是正确的,但是,为了使结果为 List<S>
,而不是 List<T>
,您必须 .map()
将 type::isInstance
谓词传递给 S
.
public static <T extends Foo, S extends T> List<S> getFromList(List<T> list, Class<S> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}
正如 @Eran 所建议的,这甚至可以简化为仅使用一种类型参数:
public static <T extends Foo> List<T> getFromList(List<Foo> list, Class<T> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}