001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.lib;
032:
033: import java.lang.reflect.Array;
034:
035: // fredt@users - 1.8.0 - enhancements
036:
037: /**
038: * Intended as an asynchronous alternative to Vector. Use HsqlLinkedList
039: * instead if its better suited.
040: *
041: * @author dnordahl@users
042: * @version 1.8.0
043: * @since 1.7.0
044: */
045: public class HsqlArrayList extends BaseList implements HsqlList {
046:
047: //fredt@users
048: /*
049: private static Reporter reporter = new Reporter();
050:
051: private static class Reporter {
052:
053: private static int initCounter = 0;
054: private static int updateCounter = 0;
055:
056: Reporter() {
057:
058: try {
059: System.runFinalizersOnExit(true);
060: } catch (SecurityException e) {}
061: }
062:
063: protected void finalize() {
064:
065: System.out.println("HsqlArrayList init count: " + initCounter);
066: System.out.println("HsqlArrayList update count: "
067: + updateCounter);
068: }
069: }
070: */
071: private static final int DEFAULT_INITIAL_CAPACITY = 10;
072: private static final float DEFAULT_RESIZE_FACTOR = 2.0f;
073: private Object[] elementData;
074: private boolean minimizeOnClear;
075:
076: /** Creates a new instance of HsqlArrayList */
077: public HsqlArrayList() {
078:
079: // reporter.initCounter++;
080: elementData = new Object[DEFAULT_INITIAL_CAPACITY];
081: }
082:
083: /**
084: * Creates a new instance of HsqlArrayList that minimizes the size when
085: * empty
086: */
087: public HsqlArrayList(boolean minimize) {
088:
089: // reporter.initCounter++;
090: elementData = new Object[DEFAULT_INITIAL_CAPACITY];
091: minimizeOnClear = minimize;
092: }
093:
094: /** Creates a new instance with the given initial capacity */
095: public HsqlArrayList(int initialCapacity) {
096:
097: // reporter.initCounter++;
098: if (initialCapacity < 0) {
099: throw new NegativeArraySizeException(
100: "Invalid initial capacity given");
101: }
102:
103: if (initialCapacity == 0) {
104: elementData = new Object[1];
105: } else {
106: elementData = new Object[initialCapacity];
107: }
108: }
109:
110: /** Inserts an element at the given index */
111: public void add(int index, Object element) {
112:
113: // reporter.updateCounter++;
114: if (index > elementCount) {
115: throw new IndexOutOfBoundsException("Index out of bounds: "
116: + index + ">" + elementCount);
117: }
118:
119: if (index < 0) {
120: throw new IndexOutOfBoundsException("Index out of bounds: "
121: + index + " < 0");
122: }
123:
124: if (elementCount >= elementData.length) {
125: increaseCapacity();
126: }
127:
128: for (int i = elementCount; i > index; i--) {
129: elementData[i] = elementData[i - 1];
130: }
131:
132: elementData[index] = element;
133:
134: elementCount++;
135: }
136:
137: /** Appends an element to the end of the list */
138: public boolean add(Object element) {
139:
140: // reporter.updateCounter++;
141: if (elementCount >= elementData.length) {
142: increaseCapacity();
143: }
144:
145: elementData[elementCount] = element;
146:
147: elementCount++;
148:
149: return true;
150: }
151:
152: /** Gets the element at given position */
153: public Object get(int index) {
154:
155: if (index >= elementCount) {
156: throw new IndexOutOfBoundsException("Index out of bounds: "
157: + index + " >= " + elementCount);
158: }
159:
160: if (index < 0) {
161: throw new IndexOutOfBoundsException("Index out of bounds: "
162: + index + " < 0");
163: }
164:
165: return elementData[index];
166: }
167:
168: /** returns the index of given object or -1 if nt found */
169: public int indexOf(Object o) {
170:
171: for (int i = 0; i < elementCount; i++) {
172: if (elementData[i].equals(o)) {
173: return i;
174: }
175: }
176:
177: return -1;
178: }
179:
180: /** Removes and returns the element at given position */
181: public Object remove(int index) {
182:
183: if (index >= elementCount) {
184: throw new IndexOutOfBoundsException("Index out of bounds: "
185: + index + " >= " + elementCount);
186: }
187:
188: if (index < 0) {
189: throw new IndexOutOfBoundsException("Index out of bounds: "
190: + index + " < 0");
191: }
192:
193: Object removedObj = elementData[index];
194:
195: for (int i = index; i < elementCount - 1; i++) {
196: elementData[i] = elementData[i + 1];
197: }
198:
199: elementCount--;
200:
201: elementData[elementCount] = null;
202:
203: if (minimizeOnClear && elementCount == 0) {
204: elementData = new Object[DEFAULT_INITIAL_CAPACITY];
205: }
206:
207: return removedObj;
208: }
209:
210: /** Replaces the element at given position */
211: public Object set(int index, Object element) {
212:
213: if (index >= elementCount) {
214: throw new IndexOutOfBoundsException("Index out of bounds: "
215: + index + " >= " + elementCount);
216: }
217:
218: if (index < 0) {
219: throw new IndexOutOfBoundsException("Index out of bounds: "
220: + index + " < 0");
221: }
222:
223: Object replacedObj = elementData[index];
224:
225: elementData[index] = element;
226:
227: return replacedObj;
228: }
229:
230: /** Returns the number of elements in the array list */
231: public final int size() {
232: return elementCount;
233: }
234:
235: private void increaseCapacity() {
236:
237: int baseSize = elementData.length == 0 ? 1 : elementData.length;
238: Object[] newArray = new Object[(int) (baseSize * DEFAULT_RESIZE_FACTOR)];
239:
240: System.arraycopy(elementData, 0, newArray, 0,
241: elementData.length);
242:
243: elementData = newArray;
244: newArray = null;
245: }
246:
247: /**
248: * Returns an Enumeration of the elements of the list. The Enumerator will
249: * NOT throw a concurrent modification exception if the list is modified
250: * during the enumeration.
251: */
252: /*
253: public Enumeration elements() {
254:
255: Enumeration en = new Enumeration() {
256:
257: private int pos = 0;
258:
259: public Object nextElement() {
260:
261: if (!hasMoreElements()) {
262: throw new NoSuchElementException("Enumeration complete");
263: }
264:
265: pos++;
266:
267: return elementData[pos - 1];
268: }
269:
270: public boolean hasMoreElements() {
271: return (pos < elementCount);
272: }
273: };
274:
275: return en;
276: }
277: */
278:
279: /** Trims the array to be the same size as the number of elements. */
280: public void trim() {
281:
282: // 0 size array is possible
283: Object[] newArray = new Object[elementCount];
284:
285: System.arraycopy(elementData, 0, newArray, 0, elementCount);
286:
287: elementData = newArray;
288: newArray = null;
289: }
290:
291: // fredt@users
292: public void clear() {
293:
294: if (minimizeOnClear
295: && elementData.length > DEFAULT_INITIAL_CAPACITY) {
296: elementData = new Object[DEFAULT_INITIAL_CAPACITY];
297: elementCount = 0;
298:
299: return;
300: }
301:
302: for (int i = 0; i < elementCount; i++) {
303: elementData[i] = null;
304: }
305:
306: elementCount = 0;
307: }
308:
309: public void setSize(int newSize) {
310:
311: if (newSize < elementCount) {
312: if (minimizeOnClear && newSize == 0
313: && elementData.length > DEFAULT_INITIAL_CAPACITY) {
314: elementData = new Object[DEFAULT_INITIAL_CAPACITY];
315: elementCount = 0;
316:
317: return;
318: }
319:
320: for (int i = newSize; i < elementCount; i++) {
321: elementData[i] = null;
322: }
323: }
324:
325: elementCount = newSize;
326:
327: for (; elementCount > elementData.length;) {
328: increaseCapacity();
329: }
330: }
331:
332: // fredt@users
333: public Object[] toArray() {
334:
335: Object[] a = new Object[elementCount];
336:
337: System.arraycopy(elementData, 0, a, 0, elementCount);
338:
339: return a;
340: }
341:
342: public Object[] toArray(int start, int limit) {
343:
344: Object[] a = new Object[elementCount - limit];
345:
346: System
347: .arraycopy(elementData, start, a, 0, elementCount
348: - limit);
349:
350: return a;
351: }
352:
353: /**
354: * Copies all elements of the list to a[]. It is assumed a[] is of the
355: * correct type. If a[] is too small, a new array or the same type is
356: * returned. If a[] is larger, only the list elements are copied and no
357: * other change is made to the array.
358: * Differs from the implementation in java.util.ArrayList in the second
359: * aspect.
360: */
361: public Object toArray(Object a) {
362:
363: if (Array.getLength(a) < elementCount) {
364: a = Array.newInstance(a.getClass().getComponentType(),
365: elementCount);
366: }
367:
368: System.arraycopy(elementData, 0, a, 0, elementCount);
369:
370: return a;
371: }
372:
373: public void sort(ObjectComparator c) {
374:
375: if (elementCount < 2) {
376: return;
377: }
378:
379: Sort.sort(elementData, c, 0, elementCount - 1);
380: }
381:
382: public Object[] getArray() {
383: return elementData;
384: }
385: }
|