5.19. Counting Objects in a Collection

Problem

You need to count the number of times an object occurs in a Collection.

Solution

Use CollectionUtils methods countMatches() or cardinality() . countMatches( ) takes a Collection and a Predicate, returning the number of elements that satisfy that Predicate. cardinality( ) takes an Object and a Collection, returning the number of items equal to the supplied Object. The following example demonstrates the use of both methods to count the number of times an Object occurs in a Collection:

import java.util.*;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;

String[] array = new String[] { "A", "B", "C", "C", "B", "B" };
List stringList = Arrays.asList( array );

Predicate equalPredicate = new EqualPredicate("C");

int numberCs = CollectionUtils.countMatches( stringList, equalsPredicate );
               int numberBs = CollectionUtils.cardinality( "B", stringList );

System.out.println( "List: " + ArraUtils.toString( array ) );
System.out.println( "Number of Cs: " + numberCs );
System.out.println( "Number of Bs: " + numberBs );

When used with the EqualPredicate, countMatches( ) performs the same function as cardinality( ). This example produces the following output.

List: A, B, C, C, B, B
Number of Cs: 2
Number of Bs: 3

Discussion

countMatches( ) is not limited to counting the number of elements in a Collection equal to an object; this method can also be used to count objects that meet any arbitrary Predicate. For example, you could count the number of elements in a list that match a composite predicate or a custom predicate. The following example demonstrates the use of countMatches( ) to count the number of objects that match a custom predicate:

import java.util.*;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;

int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List intList = Arrays.asList( ArrayUtils.toObject( array ) );

Predicate isEvenPredicate = new Predicate( ) {
    public boolean evaluate(Object object) {
        Integer value = (Integer) object;
        return ( (value.intValue( ) % 2) == 0 );
    }
}

int numberEven = CollectionUtils.countMatches( intList, isEvenPredicate );

System.out.println( "List: " + ArrayUtils.toString( array ) );
System.out.println( "Number of Even Numbers: " + numberEven );

This example counts the number of even numbers in a Collection; the isEvenPredicate is an anonymous inner class that implements the Predicate interface. This Predicate is passed to CollectionUtils.countMatches( ), producing the following output:

List: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Number of Even Numbers: 5

CollectionUtils can also return a frequency Map for every object in a Collection; calling CollectionUtils.getCardinalityMap( ) returns such a Map. The keys of this Map are the distinct objects in the Collection, and the values are Integer objects representing the number of times each object appears in the Collection. The following example demonstrates the creation of a frequency Map from a list of strings:

import java.util.*;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;

String[] array = new String[] { "Red", "Blue", "Blue", "Yellow", "Red", 
"Black" };
List stringList = Arrays.asList( arrays );

Map cardinalityMap = CollectionUtils.getCardinalityMap( stringList );

System.out.println( "List: " + ArrayUtils.toString( array ) );
System.out.println( "Cardinality Map:
" + MapUtils.
debugPrint( cardinalityMap ) );

A String array is converted to a List of strings, and a frequency Map is created. This Map is printed using MapUtils.debugPrint( ) :

List: Red, Blue, Blue, Yellow, Red, Black
Cardinality Map:
{
    Red = 3
    Blue = 2
    Yellow = 1
    Black = 1
}

See Also

If you are interested in the cardinality of objects in a Collection, consider using a Bag. A Bag is a Collection that revolves around the cardinality of objects it contains. Bag objects are described in Recipe 5.6.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.54.255