我有一个按类型过滤的方法,它作为输入Collection<?> collection
和Class<T> tClass
获得。我想用FluentIterable
代替Stream
。
public static <T> List<T> filterByType(final Collection<?> filerCollection, final Class<T> classType)
{
return FluentIterable.from(filerCollection).filter(classType).toList();
}
我尝试过这种解决方案:
public static <T> List<T> typeFilter(final Collection<?> filter, final Class<T> classType) {
return (List<T>) filter.stream()
.filter(Objects::nonNull)
.map(Object.class::cast)
.collect(Collectors.toList());
}
如何在不强制返回Stream
的情况下做到这一点?
答案 0 :(得分:4)
您忘记检查元素是否甚至为T
类型。即您必须先过滤掉这些元素:
return filter.stream()
.filter(classType::isInstance) // only keep elements of type T
.map(classType::cast) // safely cast from Object to T
.collect(Collectors.toList()); // collect into a List<T>
Class#isInstance()
也直接处理null
的值,因此您不必使用filter(Object::nonNull)
。
答案 1 :(得分:1)
您应该使用classType::cast
,因为在这里您使用的是Object.class::cast
,基本上什么都不做
public static <T> List<T> typeFilter(final Collection<?> filter, final Class<T> classType) {
return filter.stream()
.filter(Objects::nonNull)
.map(classType::cast)
.collect(Collectors.toList());
}
更好的是,在您的方法链中添加filter(classType::isInstance)
答案 2 :(得分:1)
仔细查看FluentIterable::filter(Class<T>)
的功能,然后将其与映射的每个项目进行比较,并投射至req
。您的意图是过滤classType
的那些项目。
接下来,应该使用classType
而不是classType::cast
,因为所需的类已经通过Object.class::cast
传递了,并且可以直接用作方法引用。 Class<T> classType
转换为父对象Object.class::cast
,每个对象都从其继承。
这是您想要的:
Object
编辑:如另一个answer所述,也可以使用public static <T> List<T> typeFilter(final Collection<?> filter, final Class<T> classType) {
return filter.stream()
.filter(Objects::nonNull)
.filter(item -> item.getClass().equals(classType))
.map(classType::cast)
.collect(Collectors.toList());
}
。
答案 3 :(得分:0)
您可以做的另一件事(虽然可能比两步操作效率低一些)是定义如下内容:
public static <T> Function<Object, Stream<T>> instancesOf(Class<T> c) {
return o -> c.isInstance(o) ? Stream.of(c.cast(o)) : Stream.empty();
}
然后像这样使用它:
return filter.stream()
.flatMap(instancesOf(classType))
.collect(toList());