2013-02-01 138 views
0

我有一个拥有传统信息的人的列表 - 比方说图书出租。因此,我列表中的每个租赁对象都会包含一个人对象作为属性和一些出租信息。对于每个人,列表中会有1..n个条目。在Java中筛选列表

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

有没有一种很好的方法来做到这一点在一个过滤器?替代方法是扫描列表,找出人,他们的项目应该被删除,然后再应用类似

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

但我想只有一次列表遍历做到这一点。我怎样才能做到这一点?

回答

1

经历的列表两次状态谓词(一次,以确定所有的“坏”的人,第二从算法运行时的角度来看,它是完全无害的。无论您是通过列表一次还是两次,该算法都会在O(n)时间内运行。

但是,如果你真的只想看一次清单,你可以构建一个临时数据结构,跟踪每个人出现在你想摆脱的人员列表旁边的所有地方。

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

当您第一次解析列表时,您将填充这两个结构。然后通过badPeople的列表,抽出他们的Rental对象列表,并从原始列表中逐个清除那些对象。

但说实话,这感觉像很多收益没有多少打扰。

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

+0

我认为这篇文章指出了这样一个观点,即你正在使用的集合可能不合适。我认为保持一个“Map >”开始将是一条路。如果您需要订购,请使用'LinkedHashMap'。此外,Guava提供了一个'Multimap'集合集合,用于执行列表映射并负责为您创建后端列表。 –

0

使谓词有状态,以便它不仅在满足某些条件时匹配,而且如果该人被称为“坏”人。

+0

但我仍然需要两次例如应用滤镜当一个人的第二个条目符合标准时,该人被标记为“不好”,但第一个条目已经“通过”测试。 –

+0

哦,对。我错过了,对不起。不过,我认为这是不可避免的。 –

0

改为使用Iterables.filter()。根据class docs:“除非另有说明,否则此类中生成的所有迭代器都是惰性的,这意味着它们的迭代器只在绝对必要时才支持迭代。”这意味着你可以编写多个过滤器,但是只有当你自己做时才会发生一次遍历。基于坏人标准

0

排序列表(错误项第一),然后筛选使用的C-陶先生说

0

现在我需要过滤根据某些条件这份名单。如果 条目之一匹配的一定的标准,我想删除所有条目 那个人,即使其他项目不符合标准。

我认为你没有做过滤。因为过滤返回一个subCollection(过滤)在某些条件。你总是会得到相同的人员列表,但有些元素会发生变化。

你想要的东西像蟒蛇的map(list, function)。通过清单,为每个人做一些事情。

番石榴的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)