用流替换番石榴Fluent可迭代

时间:2019-05-27 20:57:25

标签: java generics java-8 java-stream guava

我有一个按类型过滤的方法,它作为输入Collection<?> collectionClass<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的情况下做到这一点?

4 个答案:

答案 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());