Reputation: 390
What I want to do is remove all elements in a collection that are less than a specified object. This is what I have:
static void removeAllLessThan(Collection c, Object x) {
for(Object a : c) if(a.compareTo(x) < 0) c.remove(a);
}
This does not work because Object has no compareTo method. What I want to know is how should I compare between objects? Also what is the natural comparator? Thank you.
Upvotes: 1
Views: 1664
Reputation: 5151
There are two ways to solve this problem.
First, you can use Comparable
Interface, which means that the method should be changed into:
static void removeAllLessThan(Collection<Comparable> c, Comparable x) {
for(Comparable a : c) if(a.compareTo(x) < 0) c.remove(a);
}
An object should be comparable to have a method called comparedTo
.
Second, you can implement a Comparator
to judge which is bigger. If you don't want the object to be comparable, which means you don't want to change the existing code to let it implement Comparable
, this is a better way. But the code will be change into:
static void removeAllLessThan(Collection c, Object x, Comparator comp) {
for(Object a : c) if(comp(a, x) < 0) c.remove(a);
}
Here is the javadoc of Comparable and Comparator.
Upvotes: 0
Reputation: 7899
Start by using generics, and let the caller declare what type of object he wants to filter by:
static <T> void removeAllLessThan(Collection<T> collection, T t) {...}
This isn't enough, however. You need to use a Comparator<T>
to provide the ordering.
static <T> void removeAllLessThan(Collection<T> collection,
Comparator<T> comparator, T t) {...}
Then, allow the user some flexibility when working with inheritance. He has to do the equivalent of t1 < t2
, but the comparator can be of any supertype of T, and the collection can be of anything that extends T:
static <T> void removeAllLessThan(Collection<? extends T> collection,
Comparator<? super T> comparator, T t) {...}
Then, there is a mistake with the deletion process. The only mechanism that can delete from a collection while iterating over it is the Iterator
. Anything else risks a ConcurrentModificationException
.
static <T> void removeAllLessThan(Iterable<? extends T> iterable,
Comparator<? super T> comparator, T t) {
for (Iterator<? extends T> it = iterable.iterator(); it.hasNext();) {
if (comparator.compare(it.next(), t) < 0) {
it.remove();
}
}
}
Note the signature change.
Finally, this is a very specific method. You will need to write lots of nearly identical methods like removeIfGreaterThan, removeIfEqualIgnoringCase, etc. Write a generic removeIf
method, with signature
public <T> removeIf(Iterable<? extends T> iterable,
Predicate<? super T> predicate){...}
Predicate
is an interface provided by lots of libraries that has just a boolean eval
method.
Upvotes: 0
Reputation: 3191
using Collection<Comparable>
instead of Collection
,and implement Comparable
to all your items in the collection. And change your method like:
static void removeAllLessThan(Collection<Comparable> c, Comparable x) {
for (Iterator<Comparable> it = c.iterator(); it.hasNext();)
if (it.next().compareTo(x) < 0)
it.remove();
}
Upvotes: 3