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)

1  
sclass CircularArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
2  
  private transient Object[] elementData;
3  
  private int size;
4  
  private int head;
5  
  private int tail;
6  
  
7  
  *(int initialCapacity) {
8  
  	if (initialCapacity < 0) {
9  
  		throw new IllegalArgumentException(
10  
  				"Illegal Capacity: " + initialCapacity);
11  
  	}
12  
  
13  
  	elementData = new Object[initialCapacity];
14  
  	size = tail = head = 0;
15  
  }
16  
  
17  
  *() { this(10); }
18  
  
19  
  *(Collection<? extends E> c) {
20  
  	elementData = c.toArray();
21  
  	tail = 0;
22  
  	size = head = elementData.length;
23  
  
24  
  	// c.toArray might (incorrectly) not return Object[] (see 6260652)
25  
  	if (elementData.getClass() != Object[].class)
26  
  		elementData = Arrays.copyOf(elementData, size, Object[].class);
27  
  }
28  
  
29  
  private void copy(Object[] src, Object[] dest) {
30  
  	System.arraycopy(src, 0, dest, 0, head);
31  
  	System.arraycopy(src, src.length + tail, 
32  
  			dest, dest.length + tail, -tail);
33  
  }
34  
  
35  
  private void ensureCapacityInternal(int minCapacity) {
36  
  	modCount++;
37  
  
38  
  	// overflow-conscious code
39  
  	if (minCapacity - elementData.length > 0)
40  
  		grow(minCapacity);
41  
  }
42  
  
43  
  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
44  
  
45  
  /**
46  
   * Increases the capacity to ensure that it can hold at least the
47  
   * number of elements specified by the minimum capacity argument.
48  
   *
49  
   * @param minCapacity the desired minimum capacity
50  
   */
51  
  private void grow(int minCapacity) {
52  
  
53  
  	// overflow-conscious code
54  
  	int oldCapacity = elementData.length;
55  
  	int newCapacity = oldCapacity + (oldCapacity >> 1);
56  
  
57  
  	if (newCapacity - minCapacity < 0)
58  
  		newCapacity = minCapacity;
59  
  
60  
  	if (newCapacity - MAX_ARRAY_SIZE > 0)
61  
  		newCapacity = hugeCapacity(minCapacity);
62  
  
63  
  	Object[] oldData = elementData;
64  
  	elementData = new Object[newCapacity];
65  
  
66  
  	copy(oldData, elementData);
67  
  }
68  
  
69  
  private static int hugeCapacity(int minCapacity) {
70  
  	if (minCapacity < 0) // overflow
71  
  		throw new OutOfMemoryError();
72  
  
73  
  	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
74  
  }
75  
  
76  
  public int size() {
77  
  	return size;
78  
  }
79  
  
80  
  public boolean isEmpty() {
81  
  	return size == 0;
82  
  }
83  
  
84  
  public boolean contains(Object o) {
85  
  	return indexOf(o) >= 0;
86  
  }
87  
  
88  
  public int indexOf(Object o) {
89  
  	if (o == null) {
90  
  		for (int i = 0; i < size; i++)
91  
  			if (elementData[pos(i)] == null)
92  
  				return i;
93  
  	} else {
94  
  		for (int i = 0; i < size; i++)
95  
  			if (o.equals(elementData[pos(i)]))
96  
  				return i;
97  
  	}
98  
  	return -1;
99  
  }
100  
  
101  
  public int lastIndexOf(Object o) {
102  
  	if (o == null) {
103  
  		for (int i = size - 1; i >= 0; i--)
104  
  			if (elementData[pos(i)] == null)
105  
  				return i;
106  
  	} else {
107  
  		for (int i = size - 1; i >= 0; i--)
108  
  			if (o.equals(elementData[pos(i)]))
109  
  				return i;
110  
  	}
111  
  	return -1;
112  
  }
113  
  
114  
  public Object clone() {
115  
  	try {
116  
  		@SuppressWarnings("unchecked")
117  
  			CircularArrayList<E> c = (CircularArrayList<E>) super.clone();
118  
  
119  
  		c.elementData = new Object[size];
120  
  		copy(elementData, c.elementData);
121  
  		c.modCount = 0;
122  
  		return c;
123  
  	} catch (CloneNotSupportedException e) {
124  
  		// this shouldn't happen, since we are Cloneable
125  
  		throw new InternalError();
126  
  	}
127  
  }
128  
  
129  
  public Object[] toArray() {
130  
  	Object[] a = new Object[size];
131  
  
132  
  	System.arraycopy(elementData, elementData.length + tail, a, 0, -tail);
133  
  	System.arraycopy(elementData, 0, a, -tail, head);
134  
  
135  
  	return a;
136  
  }
137  
  
138  
  public <T> T[] toArray(T[] a) {
139  
  	if (a.length < size) {
140  
  		// Make a new array of a's runtime type
141  
  		a = ((Object)a.getClass() == (Object)Object[].class)
142  
  				? (T[]) new Object[size]
143  
  				: (T[]) Array.newInstance(a.getClass().getComponentType(), size);
144  
  
145  
  	}
146  
  
147  
  	System.arraycopy(elementData, elementData.length + tail, a, 0, -tail);
148  
  	System.arraycopy(elementData, 0, a, -tail, head);
149  
  
150  
  	if (a.length > size) {
151  
  		a[size] = null;
152  
  	}
153  
  
154  
  	return a;
155  
  }
156  
  
157  
  private int pos(int index) {
158  
  	return (elementData.length + tail + index) % elementData.length;
159  
  }
160  
  
161  
  public E get(int index) {
162  
  	rangeCheck(index);
163  
  
164  
  	return (E) elementData[pos(index)];
165  
  }
166  
  
167  
  public E set(int index, E element) {
168  
  	rangeCheck(index);
169  
  
170  
  	int pos = pos(index);
171  
  	E oldValue = (E) elementData[pos];
172  
  	elementData[pos] = element;
173  
  	return oldValue;
174  
  }
175  
  
176  
  public boolean add(E e) {
177  
  	ensureCapacityInternal(size + 1); // Increments modCount!!
178  
  	elementData[head] = e;
179  
  	head++;
180  
  	size++;
181  
  	return true;
182  
  }
183  
  
184  
  public void add(int index, E element) {
185  
  	rangeCheckForAdd(index);
186  
  
187  
  	ensureCapacityInternal(size + 1); // Increments modCount!!
188  
  
189  
  	int i = index + tail;
190  
  	if (i <= 0) {
191  
  
192  
  		System.arraycopy(elementData, elementData.length + tail, 
193  
  						 elementData, elementData.length + tail - 1, 
194  
  						 index);
195  
  
196  
  		elementData[elementData.length + i - 1] = element;
197  
  		tail--;
198  
  	} else {
199  
  
200  
  		System.arraycopy(elementData, i, elementData, i + 1, size - index);
201  
  		elementData[i] = element;
202  
  		head++;
203  
  	}
204  
  
205  
  	size++;
206  
  }
207  
  
208  
  public E remove(int index) {
209  
  	rangeCheck(index);
210  
  
211  
  	E value = (E) elementData[pos(index)];
212  
  	fastRemove(index);
213  
  
214  
  	return value;
215  
  }
216  
  
217  
  public boolean remove(Object o) {
218  
  	if (o == null) {
219  
  		for (int index = 0; index < size; index++)
220  
  			if (elementData[pos(index)] == null) {
221  
  				fastRemove(index);
222  
  				return true;
223  
  			}
224  
  	} else {
225  
  		for (int index = 0; index < size; index++)
226  
  			if (o.equals(elementData[pos(index)])) {
227  
  				fastRemove(index);
228  
  				return true;
229  
  			}
230  
  	}
231  
  	return false;
232  
  }
233  
  
234  
  private void fastRemove(int index) {
235  
  	modCount++;
236  
  
237  
  	int i = index + tail;
238  
  	if (i < 0) {
239  
  		int numMoved = index;
240  
  		if (numMoved > 0)
241  
  			System.arraycopy(elementData, elementData.length + tail, 
242  
  							 elementData, elementData.length + tail + 1,
243  
  							 numMoved);
244  
  
245  
  		elementData[elementData.length + tail] = null; // Let gc do its work
246  
  		tail++;
247  
  	} else {
248  
  		int numMoved = size - index - 1;
249  
  		if (numMoved > 0)
250  
  			System.arraycopy(elementData, i + 1, elementData, i, numMoved);
251  
  
252  
  		head--;
253  
  		elementData[head] = null; // Let gc do its work
254  
  	}
255  
  
256  
  	size--;
257  
  }
258  
  
259  
  public void clear() {
260  
  	modCount++;
261  
  
262  
  	// Let gc do its work
263  
  	for (int i = 0; i < size; i++)
264  
  		elementData[pos(i)] = null;
265  
  
266  
  	size = tail = head = 0;
267  
  }
268  
  
269  
  public boolean addAll(Collection<? extends E> c) {
270  
  	Object[] a = c.toArray();
271  
  	int numNew = a.length;
272  
  	ensureCapacityInternal(size + numNew); // Increments modCount
273  
  	System.arraycopy(a, 0, elementData, head, numNew);
274  
  	head += numNew;
275  
  	size += numNew;
276  
  	return numNew != 0;
277  
  }
278  
  
279  
  private void rangeCheck(int index) {
280  
  	if (index >= size || index < 0) {
281  
  		throw new IndexOutOfBoundsException(
282  
  				"Index: " + index + ", Size: " + size);
283  
  	}
284  
  }
285  
  
286  
  private void rangeCheckForAdd(int index) {
287  
  	if (index > size || index < 0)
288  
  		throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
289  
  }
290  
  
291  
  private String outOfBoundsMsg(int index) {
292  
  	return "Index: " + index + ", Size: " + size;
293  
  }
294  
}

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: 429 / 1046
Version history: 5 change(s)
Referenced in: [show references]