asmuts 2004/07/15 18:28:22
Modified: src/java/org/apache/jcs/utils/struct
SortedPreferentialArray.java
Log:
working without problems, could be two operations more efficient
testing method in main
Revision Changes Path
1.2 +285 -123
jakarta-turbine-jcs/src/java/org/apache/jcs/utils/struct/SortedPreferentialArray.java
Index: SortedPreferentialArray.java
===================================================================
RCS file:
/home/cvs/jakarta-turbine-jcs/src/java/org/apache/jcs/utils/struct/SortedPreferentialArray.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SortedPreferentialArray.java 14 Jul 2004 03:33:05 -0000 1.1
+++ SortedPreferentialArray.java 16 Jul 2004 01:28:22 -0000 1.2
@@ -1,5 +1,21 @@
package org.apache.jcs.utils.struct;
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -19,12 +35,14 @@
private static final Log log =
LogFactory.getLog(SortedPreferentialArray.class);
- // prefer large means that the smalles will be removed when full.
+ // prefer large means that the smallest will be removed when full.
private boolean preferLarge = true;
private int maxSize = 0;
private int curSize = 0;
private Comparable[] array;
+ private int insertCnt = 0;
+
/**
* Consruct the array with the maximum size.
*
@@ -113,84 +131,115 @@
*/
private void insert(Comparable obj)
{
- int nLar = findNearestLargerPositionForInsert(obj);
-
- if (nLar == curSize)
+ try
{
- // this next check should be unnecessary
- // findNearestLargerPosition should only return the curSize if there is
- // room left. Check to be safe
- if (curSize < maxSize)
+ int nLar = findNearestLargerOrEqualPosition(obj);
+ if (log.isDebugEnabled())
{
- array[curSize] = obj;
- curSize++;
- if (log.isDebugEnabled())
- {
- log.debug(this.dumpArray());
- }
- if (log.isDebugEnabled())
- {
- log.debug("Inserted object at the end of the array");
- }
- return;
+ log.debug("nLar = " + nLar + " obj = " + obj);
}
- } // end if not full
- boolean isFull = false;
- if (curSize == maxSize)
- {
- isFull = true;
- }
- // The array is full, we must replace
- // remove smallest or largest to determine whether to
- // shuffle left or right to insert
- if (preferLarge)
- {
- // prefer larger, remove smallest by shifting left
- // use nLar-1 for insertion point
- int pnt = nLar;
- if (!isFull)
+ if (nLar == curSize)
{
- pnt = nLar + 1;
- }
- for (int i = 0; i < pnt; i++)
- {
- array[i] = array[i + 1];
+ // this next check should be unnecessary
+ // findNearestLargerPosition should only return the curSize if there is
+ // room left. Check to be safe
+ if (curSize < maxSize)
+ {
+ array[nLar] = obj;
+ curSize++;
+ if (log.isDebugEnabled())
+ {
+ log.debug(this.dumpArray());
+ }
+ if (log.isDebugEnabled())
+ {
+ log.debug("Inserted object at the end of the array");
+ }
+ return;
+ } // end if not full
}
- array[nLar - 1] = obj;
- if (log.isDebugEnabled())
+
+ boolean isFull = false;
+ if (curSize == maxSize)
{
- log.debug("Inserted object at " + (nLar - 1));
+ isFull = true;
}
- }
- else
- {
- // prefer smaller, remove largest by shifting right
- // use nLar for insertion point
- int pnt = nLar + 1;
- if (!isFull)
+
+ // The array is full, we must replace
+ // remove smallest or largest to determine whether to
+ // shuffle left or right to insert
+ if (preferLarge)
{
- pnt = nLar;
+ if (isFull)
+ {
+ // is full, prefer larger, remove smallest by shifting left
+ int pnt = nLar - 1; // set iteration stop point
+ for (int i = 0; i < pnt; i++)
+ {
+ array[i] = array[i + 1];
+ }
+ // use nLar-1 for insertion point
+ array[nLar - 1] = obj;
+ if (log.isDebugEnabled())
+ {
+ log.debug("Inserted object at " + (nLar - 1));
+ }
+ }
+ else
+ {
+ // not full, shift right from spot
+ int pnt = nLar; // set iteration stop point
+ for (int i = curSize; i > pnt; i--)
+ {
+ array[i] = array[i - 1];
+ }
+ // use nLar-1 for insertion point
+ array[nLar] = obj;
+ curSize++;
+ if (log.isDebugEnabled())
+ {
+ log.debug("Inserted object at " + (nLar));
+ }
+ }
}
- for (int i = curSize - 1; i > pnt; i--)
+ else
{
- array[i] = array[i - 1];
+ // prefer smaller, remove largest by shifting right
+ // use nLar for insertion point
+ int pnt = nLar + 1;
+ if (!isFull)
+ {
+ pnt = nLar;
+ }
+ for (int i = curSize; i > pnt; i--)
+ {
+ array[i] = array[i - 1];
+ }
+ array[nLar] = obj;
+ if (log.isDebugEnabled())
+ {
+ log.debug("Inserted object at " + nLar);
+ }
}
- array[nLar] = obj;
+
if (log.isDebugEnabled())
{
- log.debug("Inserted object at " + nLar);
+ log.debug(this.dumpArray());
}
}
+ catch (Exception e)
+ {
+ log.error("Insertion problem" + this.dumpArray(), e);
+ }
- //} // end if full
-
- // TODO handle case where the new item is less than the largest and the
- // array is not full.
-
- if (log.isDebugEnabled())
+ insertCnt++;
+ if (insertCnt % 100 == 0)
{
- log.debug(this.dumpArray());
+ if (log.isInfoEnabled())
+ {
+ log.info(this.dumpArray());
+ }
}
} // end insert
@@ -198,7 +247,6 @@
/**
* Determines whether the preference is for large or small.
*
- *
* @param pref boolean
*/
public void setPreferLarge(boolean pref)
@@ -207,39 +255,48 @@
}
/**
- * Returns and removes the nearerLarger from the aray
+ * Returns and removes the nearer larger or equal object from the aray.
*
* @param obj Comparable
* @return Comparable
*/
public Comparable takeNearestLargerOrEqual(Comparable obj)
{
- int pos = findNearestOccupiedLargerOrEqualPosition(obj);
- if (pos == -1)
- {
- return null;
- }
-
Comparable retVal = null;
try
{
- retVal = array[pos];
- remove(pos);
+ int pos = findNearestOccupiedLargerOrEqualPosition(obj);
+ if (pos == -1)
+ {
+ return null;
+ }
+
+ try
+ {
+ retVal = array[pos];
+ remove(pos);
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("obj = " + obj + " || retVal = " + retVal);
+ }
}
catch (Exception e)
{
- log.error(e);
- }
-
- if (log.isDebugEnabled())
- {
- log.debug("obj = " + obj + " || retVal = " + retVal);
+ log.error("Take problem" + this.dumpArray(), e);
}
-
return retVal;
}
/**
+ * This determines the position in the array that is occupied by an object
+ * that is larger or equal to the argument. If none exists, -1 is
+ * returned.
*
* @param obj Object
* @return Object
@@ -253,7 +310,7 @@
}
// this gives us an insert position.
- int pos = findNearestLargerPositionForInsert(obj);
+ int pos = findNearestLargerOrEqualPosition(obj);
// see if the previous will do to handle the empty insert spot position
if (pos == curSize)
{ //&& curSize < maxSize ) {
@@ -270,114 +327,165 @@
return pos;
}
- private void remove(int position)
- {
- // suffle left from removal point
- for (int i = position; i < curSize - 1; i++)
- {
- array[i] = array[i + 1];
- }
- curSize--;
- }
-
/**
+ * This method determines the position where an insert should take place
+ * for a given object. With some additional checking, this can also be used
+ * to find an object matching or greater than the argument.
+ *
* If the array is not full and the current object is larger than all
* the rest the first open slot at the end will be returned.
*
- * If you want to find the takePosition, you have to calculate it.
- *
* If the object is larger than the largest and it is full, it
* will return the last position.
*
- * Returns the position of the nearest to or equal to the larger object.
- * Returns -1 if the object is null.
+ * If the array is empty, the first spot is returned.
+ *
+ * If the object is smaller than all the rests, the first position is
+ * returned. The caller must decide what to do given the preference.
+ *
+ * Returns the position of the object nearest to or equal to the larger object.
+ *
+ * If you want to find the takePosition, you have to calculate it.
+ * findNearestOccupiedLargerOrEqualPosition will calculate this for you
*
* @param obj Comparable
* @return int
*/
- private int findNearestLargerPositionForInsert(Comparable obj)
+ private int findNearestLargerOrEqualPosition(Comparable obj)
{
+ // do nothing if a null was passed in
if (obj == null)
{
return -1;
}
+ // return the first spot if the array is empty
if (curSize <= 0)
{
return 0;
}
+ // mark the numer to be returned, the greaterPos as unset
int greaterPos = -1;
+ // prepare for a binary search
+ int curPos = (curSize - 1) / 2;
+ int prevPos = -1;
try
{
-
- int curPos = (curSize - 1) / 2;
- int prevPos = -1;
+ // set the loop exit flag to false
boolean done = false;
// check the ends
+ // return insert position 0 if obj is smaller
+ // than the smallest. the caller can determine what to
+ // do with this, depending on the preference setting
if (obj.compareTo(getSmallest()) <= 0)
{
+ //LESS THAN OR EQUAL TO SMALLEST
+ if (log.isDebugEnabled())
+ {
+ log.debug(obj + " is smaller than or equal to " + getSmallest());
+ }
greaterPos = 0;
done = true;
+ //return greaterPos;
}
-
- if (obj.compareTo(getLargest()) >= 0)
+ else
{
- if (curSize == maxSize)
+ //GREATER THAN SMALLEST
+ if (log.isDebugEnabled())
{
- greaterPos = curSize - 1;
- done = true;
+ log.debug(obj + " is bigger than " + getSmallest());
+ }
+
+ // return the largest position if obj is larger
+ // than the largest. the caller can determine what to
+ // do with this, depending on the preference setting
+ if (obj.compareTo(getLargest()) >= 0)
+ {
+ if (curSize == maxSize)
+ {
+ // there is no room left in the array, return the last spot
+ greaterPos = curSize - 1;
+ done = true;
+ }
+ else
+ {
+ // there is room left in the array
+ greaterPos = curSize;
+ done = true;
+ }
}
else
{
- greaterPos = curSize;
- done = true;
+ // the obj is less than the largest, so we know that the last
+ // item is larger
+ greaterPos = curSize - 1;
}
}
- else
- {
- greaterPos = curSize - 1;
- }
+ ///////////////////////////////////////////////////////////////////////
+ // begin binary search for insertion spot
while (!done)
{
if (log.isDebugEnabled())
{
- log.debug("curPos = " + curPos + "; greaterPos = " + greaterPos +
+ log.debug("\n curPos = " + curPos + "; greaterPos = " + greaterPos +
"; prevpos = " + prevPos);
}
- if (curPos == prevPos)
+ // get out of loop if we have come to the end or passed it
+ if (curPos == prevPos || curPos >= curSize)
{
done = true;
break;
}
- // object at current position is equakl to the obj, use this,
+ else
+
+ // EQUAL TO
+ // object at current position is equal to the obj, use this,
// TODO could avoid some shuffling if I found a lower pos.
if (array[curPos].compareTo(obj) == 0)
{
+ if (log.isDebugEnabled())
+ {
+ log.debug(array[curPos] + " is equal to " + obj);
+ }
greaterPos = curPos;
done = true;
break;
}
- // object at current position is greater than the obj, go left
- if (array[curPos].compareTo(obj) >= 0)
+ else
+
+ // GREATER THAN
+ // array object at current position is greater than the obj, go left
+ if (array[curPos].compareTo(obj) > 0)
{
- // set the smalelst greater equal to the current position
+ if (log.isDebugEnabled())
+ {
+ log.debug(array[curPos] + " is greater than " + obj);
+ }
+ // set the smallest greater equal to the current position
greaterPos = curPos;
// set the current position to
// set the previous position to the current position
- int newPos = curPos + prevPos / 2;
+ int newPos = Math.min( curPos, (curPos + prevPos) / 2 );
prevPos = curPos;
curPos = newPos;
}
else
+
+ // LESS THAN
+ // the object at the current position is smaller, go right
+ if (array[curPos].compareTo(obj) < 0)
{
- // the object at the current position is smaller, go right
- if ( ( (greaterPos != -1) && greaterPos - curPos < 0))
+ if (log.isDebugEnabled())
+ {
+ log.debug(array[curPos] + " is less than " + obj);
+ }
+ if ( (greaterPos != -1) && greaterPos - curPos < 0)
{
done = true;
break; //return greaterPos;
@@ -387,35 +495,61 @@
int newPos = 0;
if (prevPos > curPos)
{
- newPos = (curPos + prevPos) / 2;
+ newPos = Math.min( (curPos + prevPos) / 2, curSize);
}
else
if (prevPos == -1)
{
- newPos = (curSize + curPos) / 2;
+ newPos = Math.min( (curSize + curPos) / 2, curSize);
}
prevPos = curPos;
curPos = newPos;
}
}
} // end while
+ ///////////////////////////////////////////////////////////////////////
if (log.isDebugEnabled())
{
- log.debug("Greater Position is [" + greaterPos + "]");
- log.debug("array[greaterPos] [" + array[greaterPos] + "]");
+ log.debug("Greater Position is [" + greaterPos + "]" +
+ " array[greaterPos] [" + array[greaterPos] + "]");
}
}
catch (Exception e)
{
- log.error(this.dumpArray(), e);
+ log.error("\n curPos = " + curPos + "; greaterPos = " + greaterPos +
+ "; prevpos = " + prevPos + " " + this.dumpArray(), e);
}
return greaterPos;
}
/**
- * Debugging method
+ * Removes the item from the array at the specified position. The remaining
+ * items to the right are shifted left.
+ * @param position int
+ */
+ private void remove(int position)
+ {
+ try
+ {
+ // suffle left from removal point
+ int end = curSize - 1;
+ for (int i = position; i < end; i++)
+ {
+ array[i] = array[i + 1];
+ }
+ curSize--;
+ }
+ catch (Exception e)
+ {
+ log.error("Remove problem" + this.dumpArray(), e);
+ }
+
+ }
+
+ /**
+ * Debugging method to return a human readable display of array data.
*/
private String dumpArray()
{
@@ -430,6 +564,34 @@
buf.append("\n " + i + "=" + array[i]);
}
return buf.toString();
+ }
+
+ /**
+ * Simple testing program.
+ *
+ * @param args String[]
+ */
+ public static void main(String args[])
+ {
+
+ SortedPreferentialArray array = new SortedPreferentialArray(25);
+ //array.setPreferLarge( false );
+ array.setPreferLarge( true );
+ String[] elem =
+ {
+ "10", "11", "01", "02", "03", "04", "05", "08", "07",
+ "06", "09", "12", "13", "15", "14", "20", "25", "29", "28", "16", "17",
+ "96", "00", "72", "39", "55", "44", "26", "22", "59", "38", "16", "27"};
+
+ for (int i = 0; i < elem.length; i++)
+ {
+ array.add(elem[i]);
+ System.out.println(array.dumpArray());
+ }
+
+ //String t = "01";
+ //System.out.print(t.compareTo("10"));
+
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]