001: // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
002:
003: package jodd.util.collection;
004:
005: import java.io.ObjectInputStream;
006: import java.io.ObjectOutputStream;
007: import java.io.Serializable;
008: import java.io.IOException;
009:
010: /**
011: * ArrayList of byte primitives.
012: */
013: public class ByteArrayList implements Serializable {
014:
015: private byte[] array;
016: private int size;
017:
018: public static int INITIAL_CAPACITY = 10;
019:
020: /**
021: * Constructs an empty list with an initial capacity.
022: */
023: public ByteArrayList() {
024: this (INITIAL_CAPACITY);
025: }
026:
027: /**
028: * Constructs an empty list with the specified initial capacity.
029: */
030: public ByteArrayList(int initialCapacity) {
031: if (initialCapacity < 0) {
032: throw new IllegalArgumentException(
033: "Capacity can't be negative: " + initialCapacity);
034: }
035: array = new byte[initialCapacity];
036: size = 0;
037: }
038:
039: /**
040: * Constructs a list containing the elements of the specified array.
041: * The list instance has an initial capacity of 110% the size of the specified array.
042: */
043: public ByteArrayList(byte[] data) {
044: array = new byte[(int) (data.length * 1.1) + 1];
045: size = data.length;
046: System.arraycopy(data, 0, array, 0, size);
047: }
048:
049: // ---------------------------------------------------------------- conversion
050:
051: /**
052: * Returns an array containing all of the elements in this list in the correct order.
053: */
054: public byte[] toArray() {
055: byte[] result = new byte[size];
056: System.arraycopy(array, 0, result, 0, size);
057: return result;
058: }
059:
060: // ---------------------------------------------------------------- methods
061:
062: /**
063: * Returns the element at the specified position in this list.
064: */
065: public byte get(int index) {
066: checkRange(index);
067: return array[index];
068: }
069:
070: /**
071: * Returns the number of elements in this list.
072: */
073: public int size() {
074: return size;
075: }
076:
077: /**
078: * Removes the element at the specified position in this list.
079: * Shifts any subsequent elements to the left (subtracts
080: * one from their indices).
081: *
082: * @param index the index of the element to remove
083: * @return the value of the element that was removed
084: * @throws UnsupportedOperationException when this operation is not
085: * supported
086: * @throws IndexOutOfBoundsException if the specified index is out of range
087: */
088: public byte remove(int index) {
089: checkRange(index);
090: byte oldval = array[index];
091: int numtomove = size - index - 1;
092: if (numtomove > 0) {
093: System.arraycopy(array, index + 1, array, index, numtomove);
094: }
095: size--;
096: return oldval;
097: }
098:
099: /**
100: * Removes from this list all of the elements whose index is between fromIndex,
101: * inclusive and toIndex, exclusive. Shifts any succeeding elements to the left (reduces their index).
102: */
103: public void removeRange(int fromIndex, int toIndex) {
104: checkRange(fromIndex);
105: checkRange(toIndex);
106: if (fromIndex >= toIndex) {
107: return;
108: }
109: int numtomove = size - toIndex;
110: if (numtomove > 0) {
111: System.arraycopy(array, toIndex, array, fromIndex,
112: numtomove);
113: }
114: size -= (toIndex - fromIndex);
115: }
116:
117: /**
118: * Replaces the element at the specified position in this list with the specified element.
119: *
120: * @param index the index of the element to change
121: * @param element the value to be stored at the specified position
122: * @return the value previously stored at the specified position
123: */
124: public byte set(int index, byte element) {
125: checkRange(index);
126: byte oldval = array[index];
127: array[index] = element;
128: return oldval;
129: }
130:
131: /**
132: * Appends the specified element to the end of this list.
133: */
134: public void add(byte element) {
135: ensureCapacity(size + 1);
136: array[size++] = element;
137: }
138:
139: /**
140: * Inserts the specified element at the specified position in this list.
141: * Shifts the element currently at that position (if any) and any subsequent
142: * elements to the right (adds one to their indices).
143: *
144: * @param index the index at which to insert the element
145: * @param element the value to insert
146: */
147: public void add(int index, byte element) {
148: checkRangeIncludingEndpoint(index);
149: ensureCapacity(size + 1);
150: int numtomove = size - index;
151: System.arraycopy(array, index, array, index + 1, numtomove);
152: array[index] = element;
153: size++;
154: }
155:
156: /**
157: * Appends all of the elements in the specified array to the end of this list.
158: */
159: public void addAll(byte[] data) {
160: int dataLen = data.length;
161: if (dataLen == 0) {
162: return;
163: }
164: int newcap = size + (int) (dataLen * 1.1) + 1;
165: ensureCapacity(newcap);
166: System.arraycopy(data, 0, array, size, dataLen);
167: size += dataLen;
168: }
169:
170: /**
171: * Appends all of the elements in the specified array at the specified position in this list.
172: */
173: public void addAll(int index, byte[] data) {
174: int dataLen = data.length;
175: if (dataLen == 0) {
176: return;
177: }
178: int newcap = size + (int) (dataLen * 1.1) + 1;
179: ensureCapacity(newcap);
180: System.arraycopy(array, index, array, index + dataLen, size
181: - index);
182: System.arraycopy(data, 0, array, index, dataLen);
183: size += dataLen;
184: }
185:
186: /**
187: * Removes all of the elements from this list.
188: * The list will be empty after this call returns.
189: */
190: public void clear() {
191: size = 0;
192: }
193:
194: // ---------------------------------------------------------------- search
195:
196: /**
197: * Returns true if this list contains the specified element.
198: */
199: public boolean contains(byte data) {
200: for (int i = 0; i < size; i++) {
201: if (array[i] == data) {
202: return true;
203: }
204: }
205: return false;
206: }
207:
208: /**
209: * Searches for the first occurence of the given argument.
210: */
211: public int indexOf(byte data) {
212: for (int i = 0; i < size; i++) {
213: if (array[i] == data) {
214: return i;
215: }
216: }
217: return -1;
218: }
219:
220: /**
221: * Returns the index of the last occurrence of the specified object in this list.
222: */
223: public int lastIndexOf(byte data) {
224: for (int i = size - 1; i >= 0; i--) {
225: if (array[i] == data) {
226: return i;
227: }
228: }
229: return -1;
230: }
231:
232: /**
233: * Tests if this list has no elements.
234: */
235: public boolean isEmpty() {
236: return size == 0;
237: }
238:
239: // ---------------------------------------------------------------- capacity
240:
241: /**
242: * Increases the capacity of this ArrayList instance, if necessary,
243: * to ensure that it can hold at least the number of elements specified by
244: * the minimum capacity argument.
245: */
246: public void ensureCapacity(int mincap) {
247: if (mincap > array.length) {
248: int newcap = ((array.length * 3) >> 1) + 1;
249: byte[] olddata = array;
250: array = new byte[newcap < mincap ? mincap : newcap];
251: System.arraycopy(olddata, 0, array, 0, size);
252: }
253: }
254:
255: /**
256: * Trims the capacity of this instance to be the list's current size.
257: * An application can use this operation to minimize the storage of some instance.
258: */
259: public void trimToSize() {
260: if (size < array.length) {
261: byte[] olddata = array;
262: array = new byte[size];
263: System.arraycopy(olddata, 0, array, 0, size);
264: }
265: }
266:
267: // ---------------------------------------------------------------- serializable
268:
269: private void writeObject(ObjectOutputStream out) throws IOException {
270: out.defaultWriteObject();
271: out.writeInt(array.length);
272: for (int i = 0; i < size; i++) {
273: out.writeByte(array[i]);
274: }
275: }
276:
277: private void readObject(ObjectInputStream in) throws IOException,
278: ClassNotFoundException {
279: in.defaultReadObject();
280: array = new byte[in.readInt()];
281: for (int i = 0; i < size; i++) {
282: array[i] = in.readByte();
283: }
284: }
285:
286: // ---------------------------------------------------------------- privates
287:
288: private void checkRange(int index) {
289: if (index < 0 || index >= size) {
290: throw new IndexOutOfBoundsException(
291: "Index should be at least 0 and less than " + size
292: + ", found " + index);
293: }
294: }
295:
296: private void checkRangeIncludingEndpoint(int index) {
297: if (index < 0 || index > size) {
298: throw new IndexOutOfBoundsException(
299: "Index should be at least 0 and at most " + size
300: + ", found " + index);
301: }
302: }
303:
304: }
|