【问题标题】:Replace guava Fluent Iterables with Streams用 Streams 替换 guava Fluent Iterables
【发布时间】:2019-05-27 20:57:25
【问题描述】:

我有一个按类型过滤的方法,它作为输入Collection<?> collectionClass<T> tClass。我想用Stream 替换FluentIterable

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 的情况下做到这一点?

【问题讨论】:

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


    【解决方案1】:

    您忘记检查您的元素是否为T 类型。 IE。您必须先过滤掉这些元素:

    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)

    【讨论】:

      【解决方案2】:

      您应该使用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) 添加到您的方法链中

      【讨论】:

        【解决方案3】:

        仔细查看FluentIterable::filter(Class&lt;T&gt;) 做了什么,并将其与映射 每个项目与classType 进行比较。您的意图是过滤classType 的那些项目。

        接下来,应该使用classType::cast 而不是Object.class::cast,因为所需的类已经通过Class&lt;T&gt; classType 并且可以直接用作方法引用。 Object.class::cast 转换为父 Object,每个对象都从该父 Object 继承。

        这是你想要的:

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

        编辑:正如另一个answer 中提到的,filter(classType::isInstance) 也可以使用。

        【讨论】:

          【解决方案4】:

          您可以做的另一件事(尽管它可能比分两步完成效率低一些)是定义如下内容:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-06-16
            • 2022-01-09
            • 1970-01-01
            • 1970-01-01
            • 2013-12-15
            • 1970-01-01
            • 1970-01-01
            • 2019-11-24
            相关资源
            最近更新 更多