【问题标题】:How to create collection from Iterable in java?如何在 Java 中从 Iterable 创建集合?
【发布时间】:2011-10-21 14:33:48
【问题描述】:

例如,我有一组几何图形:

Set<Figure> figures;

图形有两种类型:方形和圆形。

我想使用谷歌收藏获得一组正方形:

Iterables.filter(figures,squarePredicate);

但是过滤器方法返回 Iterable...如何从 Iterable 创建 Set? (在 Iterable 上不使用循环)

【问题讨论】:

    标签: java collections guava


    【解决方案1】:

    我认为您需要重新考虑您的要求。你需要一组正方形。为什么?

    一个集合给你唯一性和迭代,仅此而已。您的 Iterable 具有唯一性,因为源是一个集合,您可以迭代 Iterable 中的项目。那你为什么需要这个套装呢?

    只有两个可能的原因:您正在使用需要 Set(或 Collection)参数的 API,或者您需要以某种方式显示 Set 的大小。

    在这些情况下,请使用 Sets.newHashSet(iterable) 创建一个 Set(一方面当然需要完整迭代,另一方面:当您迭代值时,无论如何您都需要在某一时刻进行完整迭代,那么为什么不现在做呢?)。否则,只需使用 Iterable 并忘记 Set。

    【讨论】:

    • 此代码为示例。我有两种对象。我想用谷歌集合过滤一种对象,然后用集合减法得到第二种对象。
    • 小错字:Sets.newHashSet(iterable)
    【解决方案2】:

    如果您有Set,则可以使用Sets.filter 而不是Iterables.filter 并获得Set 结果。 Set 是实时视图,类似于 Iterables.filter 的结果,但它具有 Set 属性,例如快速 contains 方法。

    要创建仅包含与谓词匹配的元素的副本,您可以按照其他人的建议使用ImmutableSet.copyOfSets.newHashSet

    【讨论】:

      【解决方案3】:

      Guava 的Iterables.filter() 故意返回一个可迭代的“视图”。这种方法有两个好处:

      • 只有在真正需要时才对元素进行迭代(例如,您可以链接 Iterables.filter() 和 Iterables.transform() 调用,并在最后只迭代一次)。
      • 您可以使用ImmutableSet.copyOf(Iterables.filter(..., ...))Sets.newHashSet(Iterables.filter(..., ...))Lists.newArrayList(Iterables.filter(..., ...)) 之类的东西从视图中创建适当的集合。 Iterables.filter() 可让您选择所需的精确集合,而不是返回任意集合。

      我还注意到您似乎使用带有谓词的Iterables.filter(Iterable unfiltered, Predicate predicate) 来过滤特定类型的实例。您可能还对 Iterables.filter(Iterable unfiltered, Class type) 重载感兴趣,它过滤给定类型的所有实例,并返回具有更具体的泛型类型的 Iterable。这样可以避免尴尬的演员阵容。

      【讨论】:

        【解决方案4】:

        使用Sets.newHashSet(Iterable) 之类的东西(或任何你需要的东西)。

        【讨论】:

          【解决方案5】:

          也许可以试试 apache 集合实用程序中的 CollectionUtils.filter()?您可以在 Set 上使用它,或者在 Set 构造函数中使用生成的集合。

          【讨论】:

          • OP 做了某种状态“使用 Google 收藏”。
          • 问题是关于 Guava,而不是 Commons / Collections。问题是一样的:你需要一个完整的迭代来应用过滤器。
          • 我相信他是在描述他在使用 google 收藏时遇到的问题,而不是说必须使用它。我只是建议转向另一个方向,以防它不是强制性的。只是一个建议。
          • “你需要一个完整的迭代”是什么意思?迭代是由过滤器方法本身进行的,您不需要编写迭代。无论您使用什么工具,总会以一种或另一种方式进行迭代以过滤集合。
          【解决方案6】:

          您可以使用 Java 8 流过滤一个集合并收集到另一个集合中:

          Set<Number> integers = numbers.stream()
              .filter(x -> x instanceof Integer)
              .collect(Collectors.toSet());
          

          返回的集合是副本,而不是实时视图。

          请注意,与 Guava 的 FluentIterable.filter 不同,结果集是 Set&lt;Integer&gt;,因为 Java 不知道您已过滤掉所有非整数。如果您需要Set&lt;Integer&gt;you have to map after filtering

          Set<Integer> integers = numbers.stream()
              .filter(x -> x instanceof Integer)
              .map(x -> (Integer)x)
              .collect(Collectors.toSet());
          

          (您可以将过滤器和映射组合成一个 flatMap,但这会为每个整数引入一个临时流对象,并且不再简洁。)

          【讨论】:

            猜你喜欢
            • 2012-10-03
            • 2020-03-25
            • 2020-09-29
            • 1970-01-01
            • 2022-01-20
            • 1970-01-01
            • 2018-05-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多