views:

146

answers:

7

I wrote a util class to filter elements in java.util.Collection as follows:

public class Util{
  public static <T> void filter(Collection<T> l, Filter<T> filter) {
    Iterator<T> it= l.iterator();
    while(it.hasNext()) {
      if(!filter.match(it.next())) {
        it.remove();
      }
    }
  }
}

public interface Filter<T> {
  public boolean match(T o);
}

Questions:

  1. Do you think it's necessary to write the method?
  2. Any improvement about the method?
A: 

I think it would be cool to have a visit(T o) method defined in your Filter<T> interface. That way the filter implementation can decide what action to take on the visited object when there is a match.

Jim Tough
+1  A: 

Whether it's necessary depends on what you want to achieve. If you can use other third party libs like Google Collections, then no. If it's planned to be a one-off, then probably not. If you plan on creating different filters, then yep, looks like a good approach to keep things modular and cohesive.

One suggestion - you might want to return a Collection - that way, you have the option of returning a new filtered Collection rather than mutating the original Collection. That could be handy if you need to use it in a concurrent context.

You might also look at the responses to this similar question.

Brabster
+1  A: 

Looks nice - but we can't decide, if it's 'necessary' to write it (OK, you actually wrote it ;) )

The remove() method is not always implemented, it is labelled (optional). Some Iterators just throw an UnsupportedOperationException. You should catch it or convert it to a custom exception saying, that this collection can't be filtered.

And then you could change the method signature to

public static <T> void filter(Iterable<T> i, Filter<T> filter)

because iterators are not limited to Collections. With this utility method you could filter every 'container' that provides an iterator which allows remove operations.

Andreas_D
+1  A: 

Do you think it's necessary to write the method?

If you don't mind using a third party library then no.

Some suggestions for third party libraries that provide this functionality:

You might want to look at Functional Java which provides filter plus many other higher order functions found in true-blue functional languages.

Example:

List<Person> adults = filter(people, new F1<Person, Boolean>() {
  public Boolean f(Person p) {
    return p.getAge() > 18;
  }
});

Another alternative is using lambdaj - a library with similar goals but is much more concise than Functional Java. lambdaj doesn't cover as much ground as Functional Java though.

Example:

List<Person> adults = filter(having(on(Person.class).getAge(), greaterThan(18)), people);
missingfaktor
+2  A: 
  1. No. The guava-libraries already have this functionality. See Iterables.filter(iterableCollection, predicate) where the Predicate implements the filtering
Bozho
+1  A: 

Regarding question 1 there are already a lot of collection libraries. Filtering is offered by instance by apache common-collections CollectionUtils and google collections Iterables .

disown
+1  A: 

You should allow any Filter<? super T> not just Filter<T>.

Clients might also want to have a method that returns a new Collection instead:

public static <T> Collection<T> filter(Collection<T> unfiltered, 
    Filter<? super T> filter)
AdamStevenson