Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

294
LINES

< > BotCompany Repo | #1013598 // CircularArrayList - list with fast remove/add at both ends; not synchronized; broken?

JavaX fragment (include)

sclass CircularArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
  private transient Object[] elementData;
  private int size;
  private int head;
  private int tail;
  
  *(int initialCapacity) {
  	if (initialCapacity < 0) {
  		throw new IllegalArgumentException(
  				"Illegal Capacity: " + initialCapacity);
  	}
  
  	elementData = new Object[initialCapacity];
  	size = tail = head = 0;
  }
  
  *() { this(10); }
  
  *(Collection<? extends E> c) {
  	elementData = c.toArray();
  	tail = 0;
  	size = head = elementData.length;
  
  	// c.toArray might (incorrectly) not return Object[] (see 6260652)
  	if (elementData.getClass() != Object[].class)
  		elementData = Arrays.copyOf(elementData, size, Object[].class);
  }
  
  private void copy(Object[] src, Object[] dest) {
  	System.arraycopy(src, 0, dest, 0, head);
  	System.arraycopy(src, src.length + tail, 
  			dest, dest.length + tail, -tail);
  }
  
  private void ensureCapacityInternal(int minCapacity) {
  	modCount++;
  
  	// overflow-conscious code
  	if (minCapacity - elementData.length > 0)
  		grow(minCapacity);
  }
  
  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  
  /**
   * Increases the capacity to ensure that it can hold at least the
   * number of elements specified by the minimum capacity argument.
   *
   * @param minCapacity the desired minimum capacity
   */
  private void grow(int minCapacity) {
  
  	// overflow-conscious code
  	int oldCapacity = elementData.length;
  	int newCapacity = oldCapacity + (oldCapacity >> 1);
  
  	if (newCapacity - minCapacity < 0)
  		newCapacity = minCapacity;
  
  	if (newCapacity - MAX_ARRAY_SIZE > 0)
  		newCapacity = hugeCapacity(minCapacity);
  
  	Object[] oldData = elementData;
  	elementData = new Object[newCapacity];
  
  	copy(oldData, elementData);
  }
  
  private static int hugeCapacity(int minCapacity) {
  	if (minCapacity < 0) // overflow
  		throw new OutOfMemoryError();
  
  	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
  }
  
  public int size() {
  	return size;
  }
  
  public boolean isEmpty() {
  	return size == 0;
  }
  
  public boolean contains(Object o) {
  	return indexOf(o) >= 0;
  }
  
  public int indexOf(Object o) {
  	if (o == null) {
  		for (int i = 0; i < size; i++)
  			if (elementData[pos(i)] == null)
  				return i;
  	} else {
  		for (int i = 0; i < size; i++)
  			if (o.equals(elementData[pos(i)]))
  				return i;
  	}
  	return -1;
  }
  
  public int lastIndexOf(Object o) {
  	if (o == null) {
  		for (int i = size - 1; i >= 0; i--)
  			if (elementData[pos(i)] == null)
  				return i;
  	} else {
  		for (int i = size - 1; i >= 0; i--)
  			if (o.equals(elementData[pos(i)]))
  				return i;
  	}
  	return -1;
  }
  
  public Object clone() {
  	try {
  		@SuppressWarnings("unchecked")
  			CircularArrayList<E> c = (CircularArrayList<E>) super.clone();
  
  		c.elementData = new Object[size];
  		copy(elementData, c.elementData);
  		c.modCount = 0;
  		return c;
  	} catch (CloneNotSupportedException e) {
  		// this shouldn't happen, since we are Cloneable
  		throw new InternalError();
  	}
  }
  
  public Object[] toArray() {
  	Object[] a = new Object[size];
  
  	System.arraycopy(elementData, elementData.length + tail, a, 0, -tail);
  	System.arraycopy(elementData, 0, a, -tail, head);
  
  	return a;
  }
  
  public <T> T[] toArray(T[] a) {
  	if (a.length < size) {
  		// Make a new array of a's runtime type
  		a = ((Object)a.getClass() == (Object)Object[].class)
  				? (T[]) new Object[size]
  				: (T[]) Array.newInstance(a.getClass().getComponentType(), size);
  
  	}
  
  	System.arraycopy(elementData, elementData.length + tail, a, 0, -tail);
  	System.arraycopy(elementData, 0, a, -tail, head);
  
  	if (a.length > size) {
  		a[size] = null;
  	}
  
  	return a;
  }
  
  private int pos(int index) {
  	return (elementData.length + tail + index) % elementData.length;
  }
  
  public E get(int index) {
  	rangeCheck(index);
  
  	return (E) elementData[pos(index)];
  }
  
  public E set(int index, E element) {
  	rangeCheck(index);
  
  	int pos = pos(index);
  	E oldValue = (E) elementData[pos];
  	elementData[pos] = element;
  	return oldValue;
  }
  
  public boolean add(E e) {
  	ensureCapacityInternal(size + 1); // Increments modCount!!
  	elementData[head] = e;
  	head++;
  	size++;
  	return true;
  }
  
  public void add(int index, E element) {
  	rangeCheckForAdd(index);
  
  	ensureCapacityInternal(size + 1); // Increments modCount!!
  
  	int i = index + tail;
  	if (i <= 0) {
  
  		System.arraycopy(elementData, elementData.length + tail, 
  						 elementData, elementData.length + tail - 1, 
  						 index);
  
  		elementData[elementData.length + i - 1] = element;
  		tail--;
  	} else {
  
  		System.arraycopy(elementData, i, elementData, i + 1, size - index);
  		elementData[i] = element;
  		head++;
  	}
  
  	size++;
  }
  
  public E remove(int index) {
  	rangeCheck(index);
  
  	E value = (E) elementData[pos(index)];
  	fastRemove(index);
  
  	return value;
  }
  
  public boolean remove(Object o) {
  	if (o == null) {
  		for (int index = 0; index < size; index++)
  			if (elementData[pos(index)] == null) {
  				fastRemove(index);
  				return true;
  			}
  	} else {
  		for (int index = 0; index < size; index++)
  			if (o.equals(elementData[pos(index)])) {
  				fastRemove(index);
  				return true;
  			}
  	}
  	return false;
  }
  
  private void fastRemove(int index) {
  	modCount++;
  
  	int i = index + tail;
  	if (i < 0) {
  		int numMoved = index;
  		if (numMoved > 0)
  			System.arraycopy(elementData, elementData.length + tail, 
  							 elementData, elementData.length + tail + 1,
  							 numMoved);
  
  		elementData[elementData.length + tail] = null; // Let gc do its work
  		tail++;
  	} else {
  		int numMoved = size - index - 1;
  		if (numMoved > 0)
  			System.arraycopy(elementData, i + 1, elementData, i, numMoved);
  
  		head--;
  		elementData[head] = null; // Let gc do its work
  	}
  
  	size--;
  }
  
  public void clear() {
  	modCount++;
  
  	// Let gc do its work
  	for (int i = 0; i < size; i++)
  		elementData[pos(i)] = null;
  
  	size = tail = head = 0;
  }
  
  public boolean addAll(Collection<? extends E> c) {
  	Object[] a = c.toArray();
  	int numNew = a.length;
  	ensureCapacityInternal(size + numNew); // Increments modCount
  	System.arraycopy(a, 0, elementData, head, numNew);
  	head += numNew;
  	size += numNew;
  	return numNew != 0;
  }
  
  private void rangeCheck(int index) {
  	if (index >= size || index < 0) {
  		throw new IndexOutOfBoundsException(
  				"Index: " + index + ", Size: " + size);
  	}
  }
  
  private void rangeCheckForAdd(int index) {
  	if (index > size || index < 0)
  		throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  }
  
  private String outOfBoundsMsg(int index) {
  	return "Index: " + index + ", Size: " + size;
  }
}

Author comment

TODO: fast removal of sublist

From https://github.com/andrioli/circular-array-list/blob/master/src/main/java/br/com/ooboo/util/CircularArrayList.java

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1013598
Snippet name: CircularArrayList - list with fast remove/add at both ends; not synchronized; broken?
Eternal ID of this version: #1013598/6
Text MD5: ca6f9c7033542f5bca27965182478cb1
Author: stefan
Category: javax / collections
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2018-06-29 01:38:11
Source code size: 7312 bytes / 294 lines
Pitched / IR pitched: No / No
Views / Downloads: 428 / 1045
Version history: 5 change(s)
Referenced in: [show references]