0

我有一份提供其他信息的人员名单——比如说出租书籍。因此,我列表中的每个 Rental-object 都将包含一个 Person-object 作为属性和一些租赁信息。对于每个人,列表中将有 1..n 个条目。

现在我需要根据一些标准过滤这个列表。如果其中一个条目符合某个条件,我想删除那个人的所有条目,即使其他条目不符合条件。

有没有一种很好的方法可以在一个过滤器中做到这一点?另一种方法是扫描列表,确定应删除其条目的人员,然后应用类似

Collections2.filter(myList, new MyPredicate(peopleIWantToRemove))

但我只想通过一次性列表遍历来完成。我怎样才能做到这一点?

4

5 回答 5

1

从算法运行时的角度来看,两次遍历列表(一次确定所有“坏”人,第二次删除他们)是完全无害的。无论您遍历列表一次还是两次,算法都在 O(n) 时间内运行。

但是,如果您真的很想只浏览一次列表,您可以构建一个临时数据结构来跟踪每个人出现在您想要摆脱的人列表旁边的所有位置。

Map<Person, List<Rental>> rentalsPerPerson;
List<People> badPeople;

第一次解析列表时,会填充这两个结构。然后,您浏览 的列表badPeople,拉出他们的Rental对象列表,并从您的原始列表中一次清除那些对象。

但老实说,这让人感觉很麻烦,收获不多。

我建议这样做的方式?浏览列表两次。第一关:编一个Set坏人。第二遍:创建一个新的 output List,最初为空。浏览你原来的List. 对于每个元素,如果Person不在Bad集合中,请将条目添加到您的输出List中。

于 2013-02-01T15:14:36.053 回答
0

使谓词有状态,以便它不仅在满足某些标准时匹配,而且在该人被称为“坏”人的情况下也匹配。

于 2013-02-01T15:01:09.903 回答
0

改为使用Iterables.filter()。根据类文档:“除非另有说明,否则此类中生成的所有迭代都是惰性的,这意味着它们的迭代器仅在绝对必要时才推进支持迭代。” 这意味着您可以组合多个过滤器,但遍历只发生一次,当您自己执行时。

于 2013-02-01T15:10:30.973 回答
0

根据坏人标准排序列表(首先是坏条目),然后使用有状态谓词进行过滤,如 C-Otto 所说

于 2013-02-01T15:13:14.517 回答
0

现在我需要根据一些标准过滤这个列表。如果其中一个条目符合某个条件,我想删除那个人的所有条目,即使其他条目不符合条件。

我认为您没有进行过滤。因为过滤在某些条件下返回一个子集合(过滤)。您将始终获得相同的人员列表,但更改了某些元素。

你想要像 python 的map(list, function). 遍历列表,为每个人做一些事情。

Guava 的 collections.transform 可以做到。

public static <F,T> Collection<T> transform(Collection<F> fromCollection,
                            Function<? super F,T> function)

看看这个:

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection , com.google.common.base.Function)

于 2013-02-01T15:21:21.317 回答