Filter java.util.Collection in Java
I wrote a util class to filter elements in java.util.Collection
as f开发者_如何学JAVAollows:
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:
- Do you think it's necessary to write the method?
- Any improvement about the method?
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)
- No. The guava-libraries already have this functionality. See
Iterables.filter(iterableCollection, predicate)
where thePredicate
implements the filtering
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.
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 .
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.
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);
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.
精彩评论