diff --git a/projects/samskivert/src/java/com/samskivert/util/ListUtil.java b/projects/samskivert/src/java/com/samskivert/util/ListUtil.java new file mode 100644 index 00000000..a5fb68c3 --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/util/ListUtil.java @@ -0,0 +1,282 @@ +// +// $Id: ListUtil.java,v 1.1 2001/08/15 04:02:42 mdb Exp $ + +package com.samskivert.util; + +/** + * List util is for the times when you just can't bear the overhead of an + * {@link java.util.ArrayList} object to manage your list of objects. It + * provides a suite of list management routines that operate on bare + * {@link java.lang.Object} arrays. Some of those routines mimic the + * behavior of array lists, others provide other more specialized + * (generally faster but making requirements of the caller) list behavior. + * + *
An example is probably in order: + * + *
+ * Object[] list = null; + * String foo = "foo"; + * String bar = "bar"; + * + * // add our objects to a list + * list = ListUtil.add(list, foo); + * list = ListUtil.add(list, bar); + * + * // remove foo from the list (does so by clearing out that index, but it + * // doesn't slide subsequent elements down) + * ListUtil.clear(list, foo); + * + * // use the version of remove that calls equals() rather than just + * // checking for equality of references + * String anotherBar = "bar"; + * ListUtil.clearEqual(list, anotherBar); + * + * // append our objects to the end of the list letting list util know + * // that we're tracking the list size + * list = ListUtil.add(list, 0, foo); + * list = ListUtil.add(list, 1, bar); + * + * // remove the elements from the list, compacting it to preserve + * // element continuity + * ListUtil.remove(list, 0); + * ListUtil.remove(list, bar); + *+ * + * See the documentation for the individual functions for their exact + * behavior. + */ +public class ListUtil +{ + /** + * Adds the specified element to the first empty slot in the specified + * list. Begins searching for empty slots at zeroth index. + * + * @param list the list to which to add the element. Can be null. + * @param element the element to add. + * + * @return a reference to the list with element added (might not be + * the list you passed in due to expansion, or allocation). + */ + public static Object[] add (Object[] list, Object element) + { + return add(list, 0, element); + } + + /** + * Adds the specified element to the next empty slot in the specified + * list. Begins searching for empty slots at the specified index. This + * can be used to quickly add elements to a list that preserves + * consecutivity by calling it with the size of the list as the first + * index to check. + * + * @param list the list to which to add the element. Can be null. + * @param startIdx the index at which to start looking for a spot. + * @param element the element to add. + * + * @return a reference to the list with element added (might not be + * the list you passed in due to expansion, or allocation). + */ + public static Object[] add (Object[] list, int startIdx, Object element) + { + // make sure we've got a list to work with + if (list == null) { + list = new Object[DEFAULT_LIST_SIZE]; + } + + // search for a spot to insert yon element; assuming we'll insert + // it at the end of the list if we don't find one + int index = list.length; + int llength = list.length; // no optimizing bastards + for (int i = startIdx; i < llength; i++) { + if (list[i] == null) { + index = i; + break; + } + } + + // expand the list if necessary + if (index >= list.length) { + list = accomodate(list, index); + } + + // stick the element on in + list[index] = element; + + return list; + } + + /** + * Clears out the first element that is referentially equal to the + * supplied element (
list[idx] == element). Passing a
+ * null element to this function will cleverly tell you
+ * the index of the first null element in the array which it will have
+ * kindly overwritten with null just for good measure.
+ *
+ * @return the element that was removed or null if it was not found.
+ */
+ public static Object clear (Object[] list, Object element)
+ {
+ int llength = list.length; // no optimizing bastards
+ for (int i = 0; i < llength; i++) {
+ Object elem = list[i];
+ if (elem == element) {
+ list[i] = null;
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Clears out the first element that is functionally equal to the
+ * supplied element (list[idx].equals(element)). Passing
+ * a null element to this function will call
+ * equals(null) on all objects in the list which may
+ * cause them to choke, so don't do that unless you mean it.
+ *
+ * @return the object that was cleared from the array or null if no
+ * matching object was found.
+ */
+ public static Object clearEqual (Object[] list, Object element)
+ {
+ int llength = list.length; // no optimizing bastards
+ for (int i = 0; i < llength; i++) {
+ Object elem = list[i];
+ if (elem != null && elem.equals(element)) {
+ list[i] = null;
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Removes the first element that is referentially equal to the
+ * supplied element (list[idx] == element). The elements
+ * after the removed element will be slid down the array one spot to
+ * fill the place of the removed element.
+ *
+ * @return the object that was removed from the array or null if no
+ * matching object was found.
+ */
+ public static Object remove (Object[] list, Object element)
+ {
+ int llength = list.length; // no optimizing bastards
+ for (int i = 0; i < llength; i++) {
+ Object elem = list[i];
+ if (elem == element) {
+ System.arraycopy(list, i+1, list, i, llength-(i+1));
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Removes the first element that is functionally equal to the
+ * supplied element (list[idx].equals(element)). The
+ * elements after the removed element will be slid down the array one
+ * spot to fill the place of the removed element. Passing a null
+ * element to this function will call
+ * equals(null) on all objects in the list which may
+ * cause them to choke, so don't do that unless you mean it.
+ *
+ * @return the object that was removed from the array or null if no
+ * matching object was found.
+ */
+ public static Object removeEqual (Object[] list, Object element)
+ {
+ int llength = list.length; // no optimizing bastards
+ for (int i = 0; i < llength; i++) {
+ Object elem = list[i];
+ if (elem != null && elem.equals(element)) {
+ System.arraycopy(list, i+1, list, i, llength-(i+1));
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Removes the element at the specified index. The elements after the
+ * removed element will be slid down the array one spot to fill the
+ * place of the removed element. If a null array is supplied or one
+ * that is not large enough to accomodate this index, null is
+ * returned.
+ *
+ * @return the object that was removed from the array or null if no
+ * object existed at that location.
+ */
+ public static Object remove (Object[] list, int index)
+ {
+ int llength = list.length;
+ if (list == null || llength <= index) {
+ return null;
+ }
+
+ Object elem = list[index];
+ System.arraycopy(list, index+1, list, index, llength-(index+1));
+ return elem;
+ }
+
+ /**
+ * Creates a new list that will accomodate the specified index and
+ * copies the contents of the old list to the first.
+ */
+ protected static Object[] accomodate (Object[] list, int index)
+ {
+ int size = list.length;
+ // expand size by powers of two until we're big enough
+ while (size <= index) {
+ size *= 2;
+ }
+
+ // create a new list and copy the contents
+ Object[] newlist = new Object[size];
+ System.arraycopy(list, 0, newlist, 0, list.length);
+ return newlist;
+ }
+
+ /**
+ * Run some tests.
+ */
+ public static void main (String[] args)
+ {
+ Object[] list = null;
+ String foo = "foo";
+ String bar = "bar";
+
+ list = ListUtil.add(list, foo);
+ System.out.println("Added foo: " + StringUtil.toString(list));
+
+ list = ListUtil.add(list, bar);
+ System.out.println("Added bar: " + StringUtil.toString(list));
+
+ ListUtil.clear(list, foo);
+ System.out.println("Cleared foo: " + StringUtil.toString(list));
+
+ String newBar = "bar";
+ ListUtil.clearEqual(list, newBar);
+ System.out.println("Cleared newBar: " + StringUtil.toString(list));
+
+ list = ListUtil.add(list, 0, foo);
+ list = ListUtil.add(list, 1, bar);
+ System.out.println("Added foo+bar: " + StringUtil.toString(list));
+
+ ListUtil.remove(list, foo);
+ System.out.println("Removed foo: " + StringUtil.toString(list));
+
+ list = ListUtil.add(list, 0, foo);
+ list = ListUtil.add(list, 1, bar);
+ System.out.println("Added foo+bar: " + StringUtil.toString(list));
+
+ ListUtil.remove(list, 0);
+ System.out.println("Removed 0: " + StringUtil.toString(list));
+ }
+
+ /**
+ * The size of a list to create if we have to create one entirely
+ * from scratch rather than just expand it.
+ */
+ protected static final int DEFAULT_LIST_SIZE = 4;
+}