【发布时间】:2011-10-21 14:33:48
【问题描述】:
例如,我有一组几何图形:
Set<Figure> figures;
图形有两种类型:方形和圆形。
我想使用谷歌收藏获得一组正方形:
Iterables.filter(figures,squarePredicate);
但是过滤器方法返回 Iterable...如何从 Iterable 创建 Set? (在 Iterable 上不使用循环)
【问题讨论】:
标签: java collections guava
例如,我有一组几何图形:
Set<Figure> figures;
图形有两种类型:方形和圆形。
我想使用谷歌收藏获得一组正方形:
Iterables.filter(figures,squarePredicate);
但是过滤器方法返回 Iterable...如何从 Iterable 创建 Set? (在 Iterable 上不使用循环)
【问题讨论】:
标签: java collections guava
我认为您需要重新考虑您的要求。你需要一组正方形。为什么?
一个集合给你唯一性和迭代,仅此而已。您的 Iterable 具有唯一性,因为源是一个集合,您可以迭代 Iterable 中的项目。那你为什么需要这个套装呢?
只有两个可能的原因:您正在使用需要 Set(或 Collection)参数的 API,或者您需要以某种方式显示 Set 的大小。
在这些情况下,请使用 Sets.newHashSet(iterable) 创建一个 Set(一方面当然需要完整迭代,另一方面:当您迭代值时,无论如何您都需要在某一时刻进行完整迭代,那么为什么不现在做呢?)。否则,只需使用 Iterable 并忘记 Set。
【讨论】:
如果您有Set,则可以使用Sets.filter 而不是Iterables.filter 并获得Set 结果。 Set 是实时视图,类似于 Iterables.filter 的结果,但它具有 Set 属性,例如快速 contains 方法。
要创建仅包含与谓词匹配的元素的副本,您可以按照其他人的建议使用ImmutableSet.copyOf 或Sets.newHashSet。
【讨论】:
Guava 的Iterables.filter() 故意返回一个可迭代的“视图”。这种方法有两个好处:
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。这样可以避免尴尬的演员阵容。
【讨论】:
使用Sets.newHashSet(Iterable) 之类的东西(或任何你需要的东西)。
【讨论】:
也许可以试试 apache 集合实用程序中的 CollectionUtils.filter()?您可以在 Set 上使用它,或者在 Set 构造函数中使用生成的集合。
【讨论】:
您可以使用 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,但这会为每个整数引入一个临时流对象,并且不再简洁。)
【讨论】: