如何在java中创建Iterable的集合?

时间:2011-10-21 14:33:49

标签: java collections guava

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

Set<Figure> figures;

图有两种类型:Square和Circle。

我想使用google集合获取一组正方形:

Iterables.filter(figures,squarePredicate);

但是filter方法返回Iterable ...如何从Iterable创建Set? (不使用Iterable循环)

6 个答案:

答案 0 :(得分:15)

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

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

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

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

答案 1 :(得分:7)

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

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

答案 2 :(得分:5)

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

  • 你只需要在你真正需要时迭代这些元素(例如你可以链接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。这可以让你避免尴尬的演员阵容。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

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

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

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

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