You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by bu...@apache.org on 2002/05/26 10:59:19 UTC

DO NOT REPLY [Bug 9423] New: - Enhancing CollectionUtils with a #reject API

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=9423>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=9423

Enhancing CollectionUtils with a #reject API

           Summary: Enhancing CollectionUtils with a #reject API
           Product: Commons
           Version: unspecified
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Enhancement
          Priority: Other
         Component: Collections
        AssignedTo: commons-dev@jakarta.apache.org
        ReportedBy: BluePhelix@web.de


Enhancing CollectionUtils with a #reject API

Using the CollectionUtils#select API with predicates, one will try to reuse 
Predicates sooner or later. That means, one will define some nice Predicates 
somewhere as Class constants, e.g.

   public class MyUtilities {
      public static final Predicate FILTER_CLASS_IS_INTERFACE = new Predicate(){
         public boolean evaluate(Object o) {
            return ((Class) o.isInterface()}};
      // ...
   }

If we use this Predicate filtering a collection of Class objects, we can write

   Collection anInterfaceCollection = CollectionUtils.select(
      aClassCollection,
      MyUtilities.FILTER_CLASS_IS_INTERFACE);

OK, that's fine. And now we want to select the non-interface Class objects from 
a collection of Class objects. What can we do?

1. We can define a predicate named FILTER_CLASS_IS_CLASS. That could be done 
here, but there could be a lot of unappropriate cases. Wouldn�t it be better to 
have a kind of negation here without defining another class? 

2. We can introduce a generic class NegationPredicate like this:

   public class NegationPredicate implements Predicate {
      private final Predicate predicateToNegate;
      public NegationPredicate(Predicate predicateToNegate) {
         this.predicateToNegate = predicateToNegate;
      }
      public boolean evaluate(Object o) {
         return !this.predicateToNegate.evaluate(o);
      }
   }

Principally, there is no problem to use the composite pattern and to construct 
classes to represent a logical predicate tree. But this can only be interesting 
for special sophisticated applications, and it costs a little bit performance 
to call an #evaluate within another #evaluate for each element of a list.

I think it's better to create a special API named #reject to get the elements 
of a collection which DON'T fit to a given predicate. The example would look 
like this:

   Collection aPureClassCollection = CollectionUtils.reject(
      aClassCollection,
      MyUtilities.FILTER_CLASS_IS_INTERFACE);

How can such a #reject API be achieved? It's only necessary to implement two 
methods in class CollectionsUtil:

/** Selects all elements from inputCollection which don't match the given 
predicate
  * into an output collection
  */
public static Collection reject( Collection inputCollection, Predicate 
predicate ) {
    ArrayList answer = new ArrayList( inputCollection.size() );
    reject( inputCollection, predicate, answer );
    return answer;
}

/** Selects all elements from inputCollection which don't match the given 
predicate
  * and adds them to outputCollection
  */
public static void reject( Collection inputCollection, Predicate predicate, 
Collection outputCollection ) {
    if ( inputCollection != null && predicate != null ) {
        for ( Iterator iter = inputCollection.iterator(); iter.hasNext(); ) {
            Object item = iter.next();
            if ( !predicate.evaluate( item ) ) {
                outputCollection.add( item );
            }
        }
    }
}

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>