Filtering a list of JavaBeans with Google Guava

Solution 1:

Do it the old-fashioned way, without Guava. (Speaking as a Guava developer.)

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

You can do this with Guava, but Java isn't Python, and trying to make it into Python is just going to perpetuate awkward and unreadable code. Guava's functional utilities should be used sparingly, and only when they provide a concrete and measurable benefit to either lines of code or performance.

Solution 2:

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

If your list of names is big, you'd better transform it into a Set (HashSet, preferrably) and call contains on this set, rather than the list, because contains is O(1) for a HashSet, and O(n) for a List.

Solution 3:

Explaining your doubts from the sentence:

So far, I've thought about combining Guava with Apache beanutils, but that doesn't seem elegant.

Java, despite of being so popular, lacks first-class function support*, what is subject to change in Java 8, where you will be able to do:

Iterable <Person> filtered = filter(allPersons, (Person p) -> acceptedNames.contains(p.getName()));

With lambdas and it will be elegant.

Until then you have choose between:

  • old-school way (like @Louis wrote)
  • verbose Guava filter (@JB's answer)
  • or other functional Java libraries (@superfav's answer).

I'd also like to add to @Lois's answer that Guava-way would be to create immutable collection, because they are better than unmodifiable, which is also described in Item 15, Minimize mutability in Effective Java by Joshua Bloch**:

ImmutableList.Builder<Person> builder = ImmutableList.builder();
for (final Person p : allPersons) {
    if (acceptedNames.contains(p.getName())) {
        builder.add(p);
    }
}
ImmutableList<Person> filtered = builder.build();

(It's implementation detail that ImmutableList.Builder creates temporary ArrayList under the hood).

*: it bothers me much, I came from Python, JavaScript and Perl worlds, where functions are treated better

**: Guava and Bloch are tightly coupled in many ways ;)