/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.client; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.RandomAccess; /** * Modified {@link ArrayList} that resizes up and down by powers of 2. * * @param <T> */ @SuppressWarnings("unchecked") public class ResizingArrayList<T> extends AbstractList<T> implements RandomAccess { public static final int MIN_SHRINK_SIZE = 32; protected Object[] elementData; protected int size; public ResizingArrayList() { this(MIN_SHRINK_SIZE); } public ResizingArrayList(int initialCapacity) { this.elementData = new Object[initialCapacity]; } public ResizingArrayList(Collection<? extends T> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } @Override public T get(int index) { rangeCheck(index, false); return (T) elementData[index]; } public int getModCount() { return modCount; } public void add(int index, T element) { rangeCheck(index, true); modCount++; ensureCapacity(size+1); System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } protected void ensureCapacity(int capacity) { if (capacity <= elementData.length) { return; } int newCapacity = 1 << (32 - Integer.numberOfLeadingZeros(capacity - 1)); int lowerCapacity = newCapacity*70/99; //SQRT(2) if (lowerCapacity > capacity) { newCapacity = lowerCapacity; } elementData = Arrays.copyOf(elementData, newCapacity); } public T set(int index, T element) { rangeCheck(index, false); T old = (T) elementData[index]; elementData[index] = element; return old; } @Override public boolean addAll(Collection<? extends T> c) { return addAll(size, c); } @Override public boolean addAll(int index, Collection<? extends T> c) { rangeCheck(index, true); modCount++; int numNew = c.size(); ensureCapacity(size + numNew); for (T t : c) { elementData[index++] = t; } size += numNew; return numNew != 0; } @Override public T remove(int index) { T oldValue = get(index); modCount++; int numMoved = size - index - 1; if (numMoved > 0) { System.arraycopy(elementData, index+1, elementData, index, numMoved); } elementData[--size] = null; int halfLength = elementData.length/2; if (size <= halfLength && elementData.length > MIN_SHRINK_SIZE) { int newSize = Math.max(halfLength*99/70, MIN_SHRINK_SIZE); Object[] next = new Object[newSize]; System.arraycopy(elementData, 0, next, 0, size); elementData = next; } return oldValue; } private void rangeCheck(int index, boolean inclusive) { if (index > size || (!inclusive && index == size)) { throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); //$NON-NLS-1$ //$NON-NLS-2$ } } @Override public void clear() { modCount++; if (size <= MIN_SHRINK_SIZE) { for (int i = 0; i < size; i++) { elementData[i] = null; } } else { elementData = new Object[MIN_SHRINK_SIZE]; } size = 0; } @Override public Object[] toArray() { return Arrays.copyOf(elementData, size); } public <U extends Object> U[] toArray(U[] a) { if (a.length < size) { return (U[]) Arrays.copyOf(elementData, size, a.getClass()); } System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) { a[size] = null; } return a; } @Override public int size() { return size; } }