使用Google Guava过滤JavaBeans列表

时间:2011-12-26 14:12:46

标签: java functional-programming guava

在Java程序中,我有一个我想根据特定属性过滤的bean列表。

例如,假设我有一个Person列表,一个JavaBean,其中Person有许多属性,其中包括'name'。

我还有一个名单。

现在我想找到名字列表中名字的所有人。

使用Google Guava执行此过滤器的最佳方法是什么?

到目前为止,我已经考虑过将Guava与Apache beanutils结合起来,但这看起来并不优雅。

我还在这里找到了一个反射扩展库:http://code.google.com/p/guava-reflection/,但我不确定如何使用它(文档很少)。

有什么想法吗?

P.S。你能说我真的很想念Python列表理解吗?

8 个答案:

答案 0 :(得分:42)

没有番石榴,这是老式的做法。 (作为番石榴开发者发言。)

List<Person> filtered = Lists.newArrayList();
for(Person p : allPersons) {
   if(acceptedNames.contains(p.getName())) {
       filtered.add(p);
   }
}

你可以用Guava做到这一点,但Java不是Python,并且试图将它变成Python只会使尴尬和难以理解的代码永久存在。应该谨慎使用番石榴的功能性实用程序,并且只有当它们为代码行或性能提供具体且可衡量的好处时才会使用。

答案 1 :(得分:23)

Iterable<Person> filtered = Iterables.filter(allPersons, new Predicate<Person>() {
    @Override
    public boolean apply(Person p) {
        return acceptedNames.contains(p.getName());
    }
});

如果您的名称列表很大,您最好将其转换为Set(HashSet,首选)并在此集合上调用contains,而不是列表,因为包含Oash(1)用于HashSet,并且O (n)列表。

答案 2 :(得分:4)

我对路易斯和JB的回答表示不满。我不知道番石榴反射,也许LambdaJ可能是你想要的:

// set up
Person me = new Person("Favio");
Person luca = new Person("Luca");
Person biagio = new Person("Biagio");
Person celestino = new Person("Celestino");
Collection<Person> meAndMyFriends = asList(me, luca, biagio, celestino);

// magic
Collection<Person> filtered = filter(having(on(Person.class).getName(),
                                            isOneOf("Favio", "Luca")),
                                     meAndMyFriends);

// test
assertThat(filtered, hasItems(me, luca));
assertEquals(2, filtered.size());

或者Scala,Clojure或Groovy可能就是你想要的......

答案 3 :(得分:2)

作为番石榴反射的开发者,我很抱歉我在这么早的阶段就放弃了这个项目(我有一份日常工作,还有一个妻子和孩子:-))。我的愿景是这样的:

Iterable<Object> thingsWithNames = 
    Iterables.filter(someData,
                     // this is a Predicate, obviously
                     BeanProperties.hasBeanProperty("name", String.class));

现有代码约占60%,所以如果您有兴趣,请与我联系,也许我们可以一起完成。

答案 4 :(得分:0)

如果您在单线程应用程序中使用LinkedList(或删除操作的任何其他集合并不十分费力),则最有效的解决方案是:

final Iterator<User> userIterator = users.iterator();
while (userIterator.hasNext()) {
    if (/* your condition for exclusion */) {
        userIterator.remove();
    }
}

答案 5 :(得分:0)

使用Java8样式,您可以使用流+过滤器来实现目标。

persons.stream()
            .filter(p -> names.contains(p.getName()))
            .collect(Collectors.toList());

答案 6 :(得分:0)

使用Java8,您可以使用Collection.removeIf()

List<Person> theList = ...;
theList.removeIf(
    (Person p)->"paul".equals(p.getName())
);

这当然会修改当前列表。

答案 7 :(得分:0)

以下是使用guava使用泛型的示例,beanutils使用请求的匹配过滤任何列表

/**
 * Filter List
 * 
 * @param inputList
 * @param requestMatch
 * @param invokeMethod
 * @return
 */
public static <T> Iterable<T> predicateFilterList(List<T> inputList, final String requestMatch,
        final String invokeMethod) {
    Predicate<T> filtered = new Predicate<T>() {
        @Override
        public boolean apply(T input) {
            boolean ok = false;
            try {
                ok = BeanUtils.getProperty(input, invokeMethod).equalsIgnoreCase(requestMatch);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return ok;
        }
    };
    return Iterables.filter(inputList, filtered);
}