GullDe
GullDe

Reputation: 390

Remove elements from collection

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

Answers (3)

Wenhao Ji
Wenhao Ji

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

Eric Jablow
Eric Jablow

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

BlackJoker
BlackJoker

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

Related Questions