是否有原因
Lists.transform()
但不是
Lists.filter()
?
如何正确过滤列表?我可以用
new ArrayList(Collection2.filter())
当然可以,但是如果我理解正确的话,就不能保证我的订购顺序保持不变。
是否有原因
Lists.transform()
但不是
Lists.filter()
?
如何正确过滤列表?我可以用
new ArrayList(Collection2.filter())
当然可以,但是如果我理解正确的话,就不能保证我的订购顺序保持不变。
List.newArrayList(Iterables.filter(...))
应该代替它Lists.newArrayList(Iterables.filter(...))
。
Answers:
它没有实现,因为它将在返回的List视图上暴露出大量危险的慢速方法,例如#get(index)(会引发性能错误)。而且ListIterator也很难实现(尽管我几年前提交了一个补丁来解决)。
由于索引方法在过滤后的列表视图中效率不高,因此最好使用不包含它们的过滤后的Iterable。
filter
一致表示一个视图(以及暗示的行为)是否为Iterables.filter
,Sets.filter
等等。由于Iterables.filter
可以轻松地与copyOf
任何视图结合使用ImmutableCollection
,因此我认为这是一个不错的设计折衷(与提出其他方法和名称(例如filteredCopy
,诸如此类)无关,用于简单实用程序的组合)。
您可以使用Iterables.filter
,它肯定会保持排序。
请注意,通过构造一个新列表,您将复制元素(当然只是引用)-这样就不会在原始列表上显示实时视图。创建视图非常棘手-考虑以下情况:
Predicate<StringBuilder> predicate =
/* predicate returning whether the builder is empty */
List<StringBuilder> builders = Lists.newArrayList();
List<StringBuilder> view = Lists.filter(builders, predicate);
for (int i = 0; i < 10000; i++) {
builders.add(new StringBuilder());
}
builders.get(8000).append("bar");
StringBuilder firstNonEmpty = view.get(0);
那将不得不遍历整个原始列表,将过滤器应用于所有内容。我想这可能要求谓词匹配在视图的整个生命周期中都不会发生变化,但这并不能完全令人满意。
(请注意,这只是猜测,也许是Guava维护者之一会加入真正的原因:)
Collections2.filter.iterator
只是调用Iterables.filter
,所以结果是相同的。
Iterables.filter
,为清楚起见,我将使用该版本。
view.size()
稍后在代码中需要一个地方:)
我
new List(Collection2.filter())
当然可以使用,但是这种方式不能保证我的订购保持不变。
这不是真的 Collections2.filter()
是一个延迟评估的函数-它实际上不会过滤您的集合,直到您开始访问过滤的版本。例如,如果您遍历过滤后的版本,则过滤后的元素将以与原始集合相同的顺序从迭代器中弹出(显然要减去过滤出的元素)。
也许您认为它先进行了过滤,然后将结果转储到某种形式的任意,无序的Collection中,但是没有。
所以,如果你使用的输出Collections2.filter()
作为输入到一个新的列表,那么你的原始顺序将会被保留。
使用静态导入(和Lists.newArrayList
函数),它变得非常简洁:
List filteredList = newArrayList(filter(originalList, predicate));
请注意,虽然Collections2.filter
不会急于遍历基础集合,但Lists.newArrayList
将-它将提取已过滤集合的所有元素并将其复制到new中ArrayList
。
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
或。List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
正如乔恩(Jon)所述,您可以使用Iterables.filter(..)
或Collections2.filter(..)
,如果不需要实时取景,则可以使用ImmutableList.copyOf(Iterables.filter(..))
或,Lists.newArrayList( Iterables.filter(..))
并且将保持顺序。
如果您真的对为什么要购买感兴趣,可以访问https://github.com/google/guava/issues/505了解更多信息。