You need to prioritize
objects: removing higher priority
objects from a Collection
before lower priority
objects.
Use a
PriorityBuffer
to hold objects to be prioritized. Objects will be removed from this
Buffer
according to a priority generated with a
Comparator
. Whenever the remove( )
method is called on this Buffer
implementation, a PriorityBuffer
uses the
Comparator
to sort its contents, returning the
element of greatest priority. Using a
PriorityBuffer
without a
Comparator
causes the buffer to prioritize objects
by natural order, casting each object to
Comparable
and comparing objects with the
compareTo( )
method; all objects must implement
the Comparable
interface if no
Comparator
is supplied. The following example
demonstrates the use of a PriorityBuffer
without
supplying a
Comparator
:
import java.util.*; import org.apache.commons.collections.Buffer; import org.apache.commons.collections.buffers.PriorityBuffer; // Create a PriorityBuffer with no Comparator Buffer priority = new PriortyBuffer( ); priority.add( new Long( 2 ) ); priority.add( new Long( 1 ) ); priority.add( new Long( 20 ) ); priority.add( new Long( 7 ) ); priority.add( new Long( 18 ) ); priority.add( new Long( 1 ) ); // Print the results in priority order Iterator priorityIterator = priority.iterator( ); while( priorityIterator.hasNext( ) ) { Long value = (Long) priority.next( ); System.out.prinltn( "Value: " + value ); }
The previous example removes values from the buffer based on a natural order, and the following output is produced:
Value: 20 Value: 18 Value: 7 Value: 2 Value: 1 Value: 1
A PriorityBuffer
, like all
Buffer
implementations, is defined by the logic to
select which object to remove. If you’ve ever
visited an emergency room, you are already familiar with the inner
workings of the PriorityBuffer
. When a patient
enters the emergency room, his or her condition is evaluated by a
nurse who then assigns a severity. When a doctor moves to the next
patient, she chooses the next patient based on severity and how long
each patient has been waiting. A patient with a critical,
life-threatening condition will be treated before an individual with
a headache—the critical patient has a higher priority in the
Buffer
.
The following example models an emergency waiting room with a
PriorityBuffer
. Assume that you have a
Patient
bean with name
,
severity
, and checkIn
properties, which is defined in Example 5-5. A
patient’s severity is a number from 0 to 10, 0 being
the lowest severity and 10 being the highest. A critical patient
would be assigned a priority of 10, and a patient with a bad cold
would be assigned a severity of 0. A patient also has a
checkIn
time: this is the time he is admitted to
the waiting room, and it is used as a tie-breaker to determine
priority when two patients have the same severity
.
Example 5-5. A Patient object
package com.discursive.jccook.collections.buffers; public class Patient { private String name; private Integer severity; private Date checkIn; public class Patient( ) {} public String getName( ) { return name; } public void setName(String name) { this.name = name; } public Integer getSeverity( ) { return severity; } public void setSeverity(Integer severity) { this.severity = severity; } public Date getCheckIn( ) { return checkIn; } public void setCheckIn(Date checkIn) { this.checkIn = checkIn; } }
The PatientPriorityComparator
in
Example 5-6 prioritizes patients by severity of
condition and time since check-in. A patient with a more severe
condition takes priority over a patient with a less severe condition
who has been waiting longer, and, if two patients have the same
severity, the one who has been waiting longer gets a higher priority.
If this Comparator
is used to sort an array of
Patient
objects, the most critical patient would
be at the last index, and the least critical would be at the first
index.
Example 5-6. A Comparator to sort Patient objects by priority
package com.discursive.jccook.collections.buffers; import java.util.Comparator; public PatientPriorityComparator implements Comparator { public int compare(Object o1, Object o2) { int comparison = -1; if( o1 instanceof Patient && o2 instanceof Patient ) { Patient p1 = (Patient) o1; Patient p2 = (Patient) o2; comparison = p1.getSeverity( ).compareTo( p2.getSeverity( ) ); if( comparison == 0 ) { comparison = p1.getCheckIn( ).compareTo( p2.getCheckIn( ) ); } } return comparison; } }
When using the PriorityBuffer
with a
PatientPriorityComparator
,
Patient
objects are added to the Buffer
and remove( )
returns the
Patient
with the highest priority. Using a
PriorityBuffer
means that you do not need to worry
about constantly resorting a Collection
by
priority; this logic is completed automatically every time an object
is removed from the Buffer
. In other words, you
are delegating responsibility to a Buffer
; it
takes care of the sorting and selecting on an as-needed basis.
Example 5-7 adds three Patient
objects to a PriorityBuffer
: John Doe 1
has an ear ache, John Doe 2 has a broken back, and Jane Doe 3 has a
concussion. Both John 2 and Jane 3 have serious conditions, and,
since John 2 checked in before Jane 3, John 2 has a higher priority
than Jane 3. John 1’s condition is not nearly as
critical; therefore, his priority is much lower, and he is treated
last.
Example 5-7. Using a prioritizing buffer
package com.discursive.jccook.collections.buffers; public class WaitingRoomApp { public static void main(String[] args) { WaitingRoomApp example = new WaitingRoomApp( ); example.start( ); } public void start( ) { Buffer patients = new PriorityBuffer( new PatientPriorityComparator( ) ); Patient johnDoe1 = new Patient( ); johnDoe1.setName( "John Doe 1" ); johnDoe1.setSeverity( new Integer( 7 ) ); johnDoe1.setCheckIn( new Date( ) ); patients.add( johnDoe1 ); Patient johnDoe2 = new Patient( ); johnDoe2.setName( "John Doe 2" ); johnDoe2.setSeverity( new Integer( 9 ) ); johnDoe2.setCheckIn( new Date( ) ); patients.add( johnDoe2 ); Patient janeDoe3 = new Patient( ); janeDoe3.setName( "Jane Doe 3" ); janeDoe3.setSeverity( new Integer( 9 ) ); janeDoe3.setCheckIn( new Date( ) ); patients.add( janeDoe3 ); while( patients.size( ) > 0 ) { Patient patient = (Patient) patients.remove( ); System.out.println( "Patient: " + patient.getName( ) ); } } }
As each Patient
is treated, the
patient’s name is printed to the console:
Patient: John Doe 2 Patient: Jane Doe 3 Patient: John Doe 1
A PriorityBuffer
in Jakarta
Commons
Collections is analogous to a PriorityQueue
in
Java 5.0. For information about PriorityQueue
and
other important changes to the Collections framework in Java 5.0, see
http://java.sun.com/j2se/1.5.0/docs/api/index.html.
18.224.73.175