2

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?
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
卢声远 Shengyuan Lu
  • 31,208
  • 22
  • 85
  • 130

7 Answers7

5

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
  • 282
  • 1
  • 2
  • 4
4
  1. No. The guava-libraries already have this functionality. See Iterables.filter(iterableCollection, predicate) where the Predicate implements the filtering
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
1

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.

Community
  • 1
  • 1
brabster
  • 42,504
  • 27
  • 146
  • 186
1

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 Dolk
  • 113,398
  • 19
  • 180
  • 268
1

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
  • 90,905
  • 62
  • 285
  • 365
1

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 .

Alexander Torstling
  • 18,552
  • 7
  • 62
  • 74
0

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
  • 14,843
  • 23
  • 75
  • 96