package util; /** * collections are realy expensive so dont use them if performance is important! * use this class instead. * * the biggest problem is that every time you work with data of a a collection, * an interator object will be created wich is realy expensive and will cause * the gc to collect those iterators very often * * TODO write testcases to be shure everything works here! * * @author Spobo * * @param <T> */ public class EfficientList<T> { private static final String LOG_TAG = "Efficient List"; protected final int INIT_SIZE = 2; /** * is accessible to increase performance in loops */ protected Object[] myArray; /** * the lenght of the {@link EfficientList}, should be used in any kind of * loop */ public int myLength = 0; public EfficientList() { myArray = new Object[INIT_SIZE]; } private EfficientList(int initSize) { myArray = new Object[initSize]; } public synchronized boolean add(T x) { if (x == null) { Log.e(LOG_TAG, "null-object not allowed to be added to " + this); return false; } if (myArray == null) myArray = new Object[INIT_SIZE]; resizeArrayIfNessecary(); try { myArray[myLength] = x; myLength++; } catch (Exception e) { Log.e(LOG_TAG, "Tryed to add " + x + " at pos " + myLength + " but myArray.length is only " + myArray.length); Log.e(LOG_TAG, "The thread which caused this was " + Thread.currentThread().toString()); Log.e(LOG_TAG, "The error appeared here:"); e.printStackTrace(); } return true; } /** * there is a add request so check if there is a free slot in the array */ private void resizeArrayIfNessecary() { if (myArray.length - 1 < myLength) { // Log.i(LOG_TAG, "Resizing array " + myArray.toString()); myArray = resizeArray(myArray.length, myArray); // Log.i(LOG_TAG, "Resized to" + myArray.toString()); } } protected Object[] resizeArray(int oldSize, Object[] a) { Object[] x = new Object[oldSize * 2]; // copy old values: for (int i = 0; i < oldSize; i++) { x[i] = a[i]; } return x; } /** * removes the first appearance of x from the list. (x is handled as an * object to improve performance) * * @param x * @return */ public boolean remove(Object x) { if (x == null) return true; for (int i = 0; i < myArray.length; i++) { if (myArray[i] == x) { myLength--; removeItemFromArray(myArray, i); return true; } } return false; } protected void removeItemFromArray(Object[] a, int pos) { int i; for (i = pos; i < a.length - 1; i++) { a[i] = a[i + 1]; } a[i] = null; } /** * @param pos * should be from 0 to this.myLength-1 * @param item * @return true if the item was inserted correctly */ public boolean insert(int pos, T item) { if (pos > myLength) return false; resizeArrayIfNessecary(); int i; for (i = myArray.length - 1; i > pos; i--) { myArray[i] = myArray[i - 1]; } myArray[i] = item; myLength++; return true; } /** * @param x * the object to search for * @return -1 if object not found and the position if its found */ public int contains(T x) { if (x == null) { return -1; } if (myArray == null) { return -1; } for (int i = 0; i < myArray.length; i++) { if (myArray[i] == x) { return i; } } return -1; } @SuppressWarnings("unchecked") public T get(int pos) { if (pos >= myLength) return null; return (T) myArray[pos]; } // TODO is this method tested?? public void clear() { myLength = 0; myArray = new Object[INIT_SIZE]; } // @Override // public EfficientList<T> clone() throws CloneNotSupportedException { // EfficientList<T> c = new EfficientList<T>(); // Log.d("EfficientList", "Cloning " + this); // for (int i = 0; i < myLength; i++) { // T x = get(i); // if (x instanceof IsCloneable) { // Log.d("EfficientList", " -> " + x // + " is clonable, so cloning it"); // c.add((T) ((IsCloneable) x).clone()); // } else { // c.add(x); // } // } // return c; // } public static String arrayToString(Object[] o, int size) { String s = "array(size=" + size + ", realSize=" + o.length + ") ["; for (int i = 0; i < o.length; i++) { s += o[i] + ", "; } return s + "]"; } @Override public String toString() { return arrayToString(myArray, myLength); } @SuppressWarnings("unchecked") public void addFrom(EfficientList<T> listToCopyEveryElementFrom) { if (listToCopyEveryElementFrom == null) { Log.e(LOG_TAG, "List to get items from was null!"); return; } Object[] a = listToCopyEveryElementFrom.myArray; for (int i = 0; i < listToCopyEveryElementFrom.myLength; i++) { this.add((T) a[i]); } } public boolean isEmpty() { return myLength == 0; } /** * this method should only be used for testing and will be removed so never * use it * * @return */ @Deprecated public Object[] getArrayCopy() { return myArray; } public static String arrayToString(Object[] o) { // TODO Auto-generated method stub return arrayToString(o, o.length); } public EfficientList<T> copy() { EfficientList<T> result = new EfficientList<T>(myLength); for (int i = 0; i < this.myLength; i++) { result.add(this.get(i)); } return result; } }