/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.uwyn.rife.datastructures.collections.primitives; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * An {@link IntList} backed by an array of <code>int</code>s. * This implementation supports all optional methods. * * @since Commons Primitives 1.0 * @version $Revision: 3913 $ $Date: 2008-04-13 09:38:28 +0200 (Sun, 13 Apr 2008) $ * * @author Rodney Waldhoff * @author Robert Fischer */ public class ArrayIntList extends RandomAccessIntList implements IntList, Serializable { // constructors //------------------------------------------------------------------------- /** * Construct an empty list with the default * initial capacity. */ public ArrayIntList() { this(8); } /** * Construct an empty list with the given * initial capacity. * @throws IllegalArgumentException when <i>initialCapacity</i> is negative */ public ArrayIntList(int initialCapacity) { if(initialCapacity < 0) { throw new IllegalArgumentException("capacity " + initialCapacity); } _data = new int[initialCapacity]; _size = 0; } /** * Constructs a list containing the elements of the given collection, * in the order they are returned by that collection's iterator. * * @see ArrayIntList#addAll(com.uwyn.rife.datastructures.collections.primitives.IntCollection) * @param that the non-<code>null</code> collection of <code>int</code>s * to add * @throws NullPointerException if <i>that</i> is <code>null</code> */ public ArrayIntList(IntCollection that) { this(that.size()); addAll(that); } /** * Constructs a list by copying the specified array. * * @param array the array to initialize the collection with * @throws NullPointerException if the array is <code>null</code> */ public ArrayIntList(int[] array) { this(array.length); System.arraycopy(array, 0, _data, 0, array.length); _size = array.length; } // IntList methods //------------------------------------------------------------------------- public int get(int index) { checkRange(index); return _data[index]; } public int size() { return _size; } /** * Removes the element at the specified position in * (optional operation). Any subsequent elements * are shifted to the left, subtracting one from their * indices. Returns the element that was removed. * * @param index the index of the element to remove * @return the value of the element that was removed * * @throws UnsupportedOperationException when this operation is not * supported * @throws IndexOutOfBoundsException if the specified index is out of range */ public int removeElementAt(int index) { checkRange(index); incrModCount(); int oldval = _data[index]; int numtomove = _size - index - 1; if(numtomove > 0) { System.arraycopy(_data,index+1,_data,index,numtomove); } _size--; return oldval; } /** * Replaces the element at the specified * position in me with the specified element * (optional operation). * * @param index the index of the element to change * @param element the value to be stored at the specified position * @return the value previously stored at the specified position * * @throws UnsupportedOperationException when this operation is not * supported * @throws IndexOutOfBoundsException if the specified index is out of range */ public int set(int index, int element) { checkRange(index); incrModCount(); int oldval = _data[index]; _data[index] = element; return oldval; } /** * Inserts the specified element at the specified position * (optional operation). Shifts the element currently * at that position (if any) and any subsequent elements to the * right, increasing their indices. * * @param index the index at which to insert the element * @param element the value to insert * * @throws UnsupportedOperationException when this operation is not * supported * @throws IllegalArgumentException if some aspect of the specified element * prevents it from being added to me * @throws IndexOutOfBoundsException if the specified index is out of range */ public void add(int index, int element) { checkRangeIncludingEndpoint(index); incrModCount(); ensureCapacity(_size+1); int numtomove = _size-index; System.arraycopy(_data,index,_data,index+1,numtomove); _data[index] = element; _size++; } public void clear() { incrModCount(); _size = 0; } public boolean addAll(IntCollection collection) { return addAll(size(), collection); } public boolean addAll(int index, IntCollection collection) { if (collection.size() == 0) { return false; } checkRangeIncludingEndpoint(index); incrModCount(); ensureCapacity(_size + collection.size()); if (index != _size) { // Need to move some elements System.arraycopy(_data, index, _data, index + collection.size(), _size - index); } for (IntIterator it = collection.iterator(); it.hasNext();) { _data[index] = it.next(); index++; } _size += collection.size(); return true; } // capacity methods //------------------------------------------------------------------------- /** * Increases my capacity, if necessary, to ensure that I can hold at * least the number of elements specified by the minimum capacity * argument without growing. */ public void ensureCapacity(int mincap) { incrModCount(); if(mincap > _data.length) { int newcap = (_data.length * 3)/2 + 1; int[] olddata = _data; _data = new int[newcap < mincap ? mincap : newcap]; System.arraycopy(olddata,0,_data,0,_size); } } /** * Reduce my capacity, if necessary, to match my * current {@link #size size}. */ public void trimToSize() { incrModCount(); if(_size < _data.length) { int[] olddata = _data; _data = new int[_size]; System.arraycopy(olddata,0,_data,0,_size); } } // private methods //------------------------------------------------------------------------- private void writeObject(ObjectOutputStream out) throws IOException{ out.defaultWriteObject(); out.writeInt(_data.length); for(int i=0;i<_size;i++) { out.writeInt(_data[i]); } } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); _data = new int[in.readInt()]; for(int i=0;i<_size;i++) { _data[i] = in.readInt(); } } private final void checkRange(int index) { if(index < 0 || index >= _size) { throw new IndexOutOfBoundsException("Should be at least 0 and less than " + _size + ", found " + index); } } private final void checkRangeIncludingEndpoint(int index) { if(index < 0 || index > _size) { throw new IndexOutOfBoundsException("Should be at least 0 and at most " + _size + ", found " + index); } } // attributes //------------------------------------------------------------------------- private transient int[] _data = null; private int _size = 0; }