org/objectweb/proactive/core/util/CircularArrayList.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.core.util;
00032 
00033 import java.util.Iterator;
00034 
00035 import org.apache.log4j.Logger;
00036 import org.objectweb.proactive.core.util.log.Loggers;
00037 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00038 
00039 
00053 public class CircularArrayList extends java.util.AbstractList
00054     implements java.util.List, java.io.Serializable {
00055     static Logger logger = ProActiveLogger.getLogger(Loggers.UTIL);
00056     private static final int DEFAULT_SIZE = 5;
00057     protected Object[] array;
00058 
00059     // head points to the first logical element in the array, and
00060     // tail points to the element following the last.  This means
00061     // that the list is empty when head == tail.  It also means
00062     // that the array array has to have an extra space in it.
00063     protected int head = 0;
00064 
00065     // head points to the first logical element in the array, and
00066     // tail points to the element following the last.  This means
00067     // that the list is empty when head == tail.  It also means
00068     // that the array array has to have an extra space in it.
00069     protected int tail = 0;
00070 
00071     // Strictly speaking, we don't need to keep a handle to size,
00072     // as it can be calculated programmatically, but keeping it
00073     // makes the algorithms faster.
00074     protected int size = 0;
00075 
00076     public CircularArrayList() {
00077         this(DEFAULT_SIZE);
00078     }
00079 
00080     public CircularArrayList(int size) {
00081         array = new Object[size];
00082     }
00083 
00084     public CircularArrayList(java.util.Collection c) {
00085         tail = c.size();
00086         array = new Object[c.size()];
00087         c.toArray(array);
00088     }
00089 
00090     public String toString() {
00091         StringBuilder sb = new StringBuilder();
00092         sb.append("CircularArray size=");
00093         sb.append(size);
00094         sb.append("\n");
00095         for (int i = 0; i < size; i++) {
00096             sb.append("[");
00097             sb.append(convert(i));
00098             sb.append("]=>");
00099             sb.append(array[convert(i)]);
00100             sb.append(", ");
00101         }
00102         sb.append("\n");
00103         return sb.toString();
00104     }
00105 
00106     public static void main(String[] args) {
00107         CircularArrayList c = new CircularArrayList(5);
00108         c.add(0, new Integer(8));
00109         logger.info(c.toString());
00110         c.add(0, new Integer(7));
00111         logger.info(c.toString());
00112         c.add(0, new Integer(6));
00113         logger.info(c.toString());
00114         c.add(0, new Integer(5));
00115         logger.info(c.toString());
00116         c.add(0, new Integer(4));
00117         logger.info(c.toString());
00118         c.add(0, new Integer(3));
00119         logger.info(c.toString());
00120         c.add(0, new Integer(2));
00121         logger.info(c.toString());
00122         c.add(0, new Integer(1));
00123         logger.info(c.toString());
00124         c.add(0, new Integer(0));
00125         logger.info(c.toString());
00126     }
00127 
00128     public boolean isEmpty() {
00129         return head == tail; // or size == 0
00130     }
00131 
00132     // We use this method to ensure that the capacity of the
00133     // list will suffice for the number of elements we want to
00134     // insert.  If it is too small, we make a new, bigger array
00135     // and copy the old elements in.
00136     public void ensureCapacity(int minCapacity) {
00137         int oldCapacity = array.length;
00138         if (minCapacity > oldCapacity) {
00139             int newCapacity = ((oldCapacity * 3) / 2) + 1;
00140             if (newCapacity < minCapacity) {
00141                 newCapacity = minCapacity;
00142             }
00143             Object[] newData = new Object[newCapacity];
00144             toArray(newData);
00145             tail = size;
00146             head = 0;
00147             array = newData;
00148         }
00149     }
00150 
00151     public int size() {
00152         // the size can also be worked out each time as:
00153         // (tail + array.length - head) % array.length
00154         return size;
00155     }
00156 
00157     public boolean contains(Object elem) {
00158         return indexOf(elem) >= 0;
00159     }
00160 
00161     public int indexOf(Object elem) {
00162         if (elem == null) {
00163             for (int i = 0; i < size; i++)
00164                 if (array[convert(i)] == null) {
00165                     return i;
00166                 }
00167         } else {
00168             for (int i = 0; i < size; i++)
00169                 if (elem.equals(array[convert(i)])) {
00170                     return i;
00171                 }
00172         }
00173         return -1;
00174     }
00175 
00176     public int lastIndexOf(Object elem) {
00177         if (elem == null) {
00178             for (int i = size - 1; i >= 0; i--)
00179                 if (array[convert(i)] == null) {
00180                     return i;
00181                 }
00182         } else {
00183             for (int i = size - 1; i >= 0; i--)
00184                 if (elem.equals(array[convert(i)])) {
00185                     return i;
00186                 }
00187         }
00188         return -1;
00189     }
00190 
00191     public Object[] toArray() {
00192         return toArray(new Object[size]);
00193     }
00194 
00195     public Object[] toArray(Object[] a) {
00196         //System.out.println("head="+head+" tail="+tail+" size="+size);
00197         if (size == 0) {
00198             return a;
00199         }
00200         if (a.length < size) {
00201             a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass()
00202                                                                 .getComponentType(),
00203                     size);
00204         }
00205         if (head < tail) {
00206             System.arraycopy(array, head, a, 0, tail - head);
00207         } else {
00208             System.arraycopy(array, head, a, 0, array.length - head);
00209             System.arraycopy(array, 0, a, array.length - head, tail);
00210         }
00211         if (a.length > size) {
00212             a[size] = null;
00213         }
00214         return a;
00215     }
00216 
00217     public Object get(int index) {
00218         rangeCheck(index);
00219         return array[convert(index)];
00220     }
00221 
00222     public Object set(int index, Object element) {
00223         modCount++;
00224         rangeCheck(index);
00225         int convertedIndex = convert(index);
00226         Object oldValue = array[convertedIndex];
00227         array[convertedIndex] = element;
00228         return oldValue;
00229     }
00230 
00231     public boolean add(Object o) {
00232         modCount++;
00233         // We have to have at least one empty space
00234         ensureCapacity(size + 1 + 1);
00235         array[tail] = o;
00236         tail = (tail + 1) % array.length;
00237         size++;
00238         return true;
00239     }
00240 
00241     // This method is the main reason we re-wrote the class.
00242     // It is optimized for removing first and last elements
00243     // but also allows you to remove in the middle of the list.
00244     public Object remove(int index) {
00245         modCount++;
00246         rangeCheck(index);
00247         int pos = convert(index);
00248 
00249         // an interesting application of try/finally is to avoid
00250         // having to use local variables
00251         try {
00252             return array[pos];
00253         } finally {
00254             array[pos] = null; // Let gc do its work
00255             // optimized for FIFO access, i.e. adding to back and
00256             // removing from front
00257             if (pos == head) {
00258                 head = (head + 1) % array.length;
00259             } else if (pos == tail) {
00260                 tail = (tail - 1 + array.length) % array.length;
00261             } else {
00262                 if ((pos > head) && (pos > tail)) { // tail/head/pos
00263                     System.arraycopy(array, head, array, head + 1, pos - head);
00264                     head = (head + 1) % array.length;
00265                 } else {
00266                     System.arraycopy(array, pos + 1, array, pos, tail - pos -
00267                         1);
00268                     tail = (tail - 1 + array.length) % array.length;
00269                 }
00270             }
00271             size--;
00272         }
00273     }
00274 
00275     public void clear() {
00276         modCount++;
00277         // Let gc do its work
00278         for (int i = 0; i != size; i++) {
00279             array[convert(i)] = null;
00280         }
00281         head = tail = size = 0;
00282     }
00283 
00284     public boolean addAll(java.util.Collection c) {
00285         modCount++;
00286         int numNew = c.size();
00287 
00288         // We have to have at least one empty space
00289         ensureCapacity(size + numNew + 1);
00290         java.util.Iterator e = c.iterator();
00291         for (int i = 0; i < numNew; i++) {
00292             array[tail] = e.next();
00293             tail = (tail + 1) % array.length;
00294             size++;
00295         }
00296         return numNew != 0;
00297     }
00298 
00299     public void add(int index, Object element) {
00300         if (index == size) {
00301             add(element);
00302             return;
00303         }
00304         modCount++;
00305         rangeCheck(index);
00306         // We have to have at least one empty space
00307         ensureCapacity(size + 1 + 1);
00308         int pos = convert(index);
00309         if (pos == head) {
00310             head = (head - 1 + array.length) % array.length;
00311             array[head] = element;
00312         } else if (pos == tail) {
00313             array[tail] = element;
00314             tail = (tail + 1) % array.length;
00315         } else {
00316             if ((pos > head) && (pos > tail)) { // tail/head/pos
00317                 System.arraycopy(array, pos, array, head - 1, pos - head + 1);
00318                 head = (head - 1 + array.length) % array.length;
00319             } else { // head/pos/tail
00320                 System.arraycopy(array, pos, array, pos + 1, tail - pos);
00321                 tail = (tail + 1) % array.length;
00322             }
00323             array[pos] = element;
00324         }
00325         size++;
00326     }
00327 
00328     public boolean addAll(int index, java.util.Collection c) {
00329         boolean result = true;
00330         Iterator it = c.iterator();
00331         while (it.hasNext()) {
00332             result &= this.add(it.next());
00333         }
00334         return result;
00335     }
00336 
00337     // The convert() method takes a logical index (as if head was
00338     // always 0) and calculates the index within array
00339     private int convert(int index) {
00340         return (index + head) % array.length;
00341     }
00342 
00343     private void rangeCheck(int index) {
00344         if ((index >= size) || (index < 0)) {
00345             throw new IndexOutOfBoundsException("Index: " + index + ", Size: " +
00346                 size);
00347         }
00348     }
00349 
00350     private void writeObject(java.io.ObjectOutputStream s)
00351         throws java.io.IOException {
00352         s.writeInt(size);
00353         for (int i = 0; i != size; i++) {
00354             s.writeObject(array[convert(i)]);
00355         }
00356     }
00357 
00358     private void readObject(java.io.ObjectInputStream s)
00359         throws java.io.IOException, ClassNotFoundException {
00360         // Read in size of list and allocate array
00361         head = 0;
00362         size = tail = s.readInt();
00363         if (tail < DEFAULT_SIZE) {
00364             array = new Object[DEFAULT_SIZE];
00365         } else {
00366             array = new Object[tail];
00367         }
00368 
00369         // Read in all elements in the proper order.
00370         for (int i = 0; i < tail; i++)
00371             array[i] = s.readObject();
00372     }
00373 }

Generated on Mon Jan 22 15:16:10 2007 for ProActive by  doxygen 1.5.1