Java Tutorial/Collections/Auto Grow Array

Материал из Java эксперт
Версия от 05:04, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Adds all the elements of the given arrays into a new double-type array.

/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.
 */

import java.lang.reflect.Array;

/**
 * Operations on arrays, primitive arrays (like <code>int[]</code>) and
 * primitive wrapper arrays (like <code>Integer[]</code>).
 * 
 * This class tries to handle <code>null</code> input gracefully.
 * An exception will not be thrown for a <code>null</code>
 * array input. However, an Object array that contains a <code>null</code>
 * element may throw an exception. Each method documents its behaviour.
 *
 * @author Stephen Colebourne
 * @author Moritz Petersen
 * @author 
 * @author Maarten Coene
 * @since 2.0
 * @version $Id: ArrayUtils.java 632503 2008-03-01 00:21:52Z ggregory $
 */
public class Main {
  /**
   * Adds all the elements of the given arrays into a new array.
   * The new array contains all of the element of <code>array1</code> followed
   * by all of the elements <code>array2</code>. When an array is returned, it is always
   * a new array.
   *
   * <pre>
   * ArrayUtils.addAll(array1, null)   = cloned copy of array1
   * ArrayUtils.addAll(null, array2)   = cloned copy of array2
   * ArrayUtils.addAll([], [])         = []
   * </pre>
   *
   * @param array1  the first array whose elements are added to the new array.
   * @param array2  the second array whose elements are added to the new array.
   * @return The new double[] array.
   * @since 2.1
   */
  public static double[] addAll(double[] array1, double[] array2) {
      if (array1 == null) {
          return clone(array2);
      } else if (array2 == null) {
          return clone(array1);
      }
      double[] joinedArray = new double[array1.length + array2.length];
      System.arraycopy(array1, 0, joinedArray, 0, array1.length);
      System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
      return joinedArray;
  }
  /**
   * Shallow clones an array returning a typecast result and handling
   * <code>null</code>.
   *
   * The objects in the array are not cloned, thus there is no special
   * handling for multi-dimensional arrays.
   * 
   * This method returns <code>null</code> for a <code>null</code> input array.
   * 
   * @param array  the array to shallow clone, may be <code>null</code>
   * @return the cloned array, <code>null</code> if <code>null</code> input
   */
  public static double[] clone(double[] array) {
      if (array == null) {
          return null;
      }
      return (double[]) array.clone();
  }
}





Array-List for integer objects.

/**
 * 
 * JFreeReport : a free Java reporting library
 * 
 *
 * Project Info:  http://reporting.pentaho.org/
 *
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 *
 * 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., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * ------------
 * LongList.java
 * ------------
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 */
import java.io.Serializable;
/**
 * A Array-List for integer objects. Ints can be added to the list and will be stored in an int-array.
 * <p/>
 * Using this list for storing ints is much faster than creating java.lang.Long objects and storing them in an
 * ArrayList.
 * <p/>
 * This list is not synchronized and does not implement the full List interface. In fact, this list can only be used to
 * add new values or to clear the complete list.
 *
 * @author Thomas Morgner
 */
public class LongList implements Serializable, Cloneable
{
  /**
   * An empty array used to avoid object creation.
   */
  private static final long[] EMPTY_ARRAY = new long[0];
  /**
   * The array holding the list data.
   */
  private long[] data;
  /**
   * The size of the list.
   */
  private int size;
  /**
   * The number of free slots added on every resize.
   */
  private int increment;
  /**
   * Creates a new IntList with the given initial capacity. The capacity will also be used as increment value when
   * extending the capacity of the list.
   *
   * @param capacity the initial capacity.
   */
  public LongList(final int capacity)
  {
    data = new long[capacity];
    increment = capacity;
  }
  /**
   * Ensures, that the list backend can store at least <code>c</code> elements. This method does nothing, if the new
   * capacity is less than the current capacity.
   *
   * @param c the new capacity of the list.
   */
  private void ensureCapacity(final int c)
  {
    if (data.length <= c)
    {
      final long[] newData = new long[Math.max(data.length + increment, c + 1)];
      System.arraycopy(data, 0, newData, 0, size);
      data = newData;
    }
  }
  /**
   * Adds the given int value to the list.
   *
   * @param value the new value to be added.
   */
  public void add(final long value)
  {
    ensureCapacity(size);
    data[size] = value;
    size += 1;
  }
  /**
   * Adds the given int value to the list.
   *
   * @param value the new value to be defined.
   * @param index the position of the valur that should be redefined.
   */
  public void set(final int index, final long value)
  {
    ensureCapacity(index);
    data[index] = value;
    if (index >= size)
    {
      size = index + 1;
    }
  }

  /**
   * Returns the value at the given index.
   *
   * @param index the index
   * @return the value at the given index
   * @throws IndexOutOfBoundsException if the index is greater or equal to the list size or if the index is negative.
   */
  public long get(final int index)
  {
    if (index >= size || index < 0)
    {
      throw new IndexOutOfBoundsException("Illegal Index: " + index + " Max:" + size);
    }
    return data[index];
  }
  /**
   * Clears the list.
   */
  public void clear()
  {
    size = 0;
  }
  /**
   * Returns the number of elements in this list.
   *
   * @return the number of elements in the list
   */
  public int size()
  {
    return size;
  }
  /**
   * Copys the list contents into a new array.
   *
   * @return the list contents as array.
   */
  public long[] toArray()
  {
    if (size == 0)
    {
      return LongList.EMPTY_ARRAY;
    }
    if (size == data.length)
    {
      return (long[]) data.clone();
    }
    final long[] retval = new long[size];
    System.arraycopy(data, 0, retval, 0, size);
    return retval;
  }
  /**
   * Copys the list contents into a new array.
   *
   * @param retval the array that should receive the contents.
   * @return the list contents as array.
   */
  public long[] toArray(long[] retval)
  {
    if (retval == null || retval.length < size)
    {
      retval =  new long[size];
    }
    System.arraycopy(data, 0, retval, 0, size);
    return retval;
  }
  /**
   * Creates a copy of this list.
   *
   * @return a copy of this list.
   * @throws CloneNotSupportedException if something went wrong during the cloning.
   */
  public Object clone() throws CloneNotSupportedException
  {
    final LongList intList = (LongList) super.clone();
    intList.data = (long[]) data.clone();
    return data;
  }
}





A variable length Double Array: expanding and contracting its internal storage array as elements are added and removed.

/*
 * 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.
 */
import java.io.Serializable;
/**
 * 
 * A variable length {@link DoubleArray} implementation that automatically
 * handles expanding and contracting its internal storage array as elements are
 * added and removed.
 * 
 * 
 * The internal storage array starts with capacity determined by the
 * <code>initialCapacity</code> property, which can be set by the constructor.
 * The default initial capacity is 16. Adding elements using
 * {@link #addElement(double)} appends elements to the end of the array. When
 * there are no open entries at the end of the internal storage array, the array
 * is expanded. The size of the expanded array depends on the
 * <code>expansionMode</code> and <code>expansionFactor</code> properties.
 * The <code>expansionMode</code> determines whether the size of the array is
 * multiplied by the <code>expansionFactor</code> (MULTIPLICATIVE_MODE) or if
 * the expansion is additive (ADDITIVE_MODE -- <code>expansionFactor</code>
 * storage locations added). The default <code>expansionMode</code> is
 * MULTIPLICATIVE_MODE and the default <code>expansionFactor</code> is 2.0.
 * 
 * 
 * The {@link #addElementRolling(double)} method adds a new element to the end
 * of the internal storage array and adjusts the "usable window" of the internal
 * array forward by one position (effectively making what was the second element
 * the first, and so on). Repeated activations of this method (or activation of
 * {@link #discardFrontElements(int)}) will effectively orphan the storage
 * locations at the beginning of the internal storage array. To reclaim this
 * storage, each time one of these methods is activated, the size of the
 * internal storage array is compared to the number of addressable elements (the
 * <code>numElements</code> property) and if the difference is too large, the
 * internal array is contracted to size <code>numElements + 1.</code> The
 * determination of when the internal storage array is "too large" depends on
 * the <code>expansionMode</code> and <code>contractionFactor</code>
 * properties. If the <code>expansionMode</code> is
 * <code>MULTIPLICATIVE_MODE</code>, contraction is triggered when the ratio
 * between storage array length and <code>numElements</code> exceeds
 * <code>contractionFactor.</code> If the <code>expansionMode</code> is
 * <code>ADDITIVE_MODE,</code> the number of excess storage locations is
 * compared to <code>contractionFactor.</code>
 * 
 * 
 * To avoid cycles of expansions and contractions, the
 * <code>expansionFactor</code> must not exceed the
 * <code>contractionFactor.</code> Constructors and mutators for both of these
 * properties enforce this requirement, throwing IllegalArgumentException if it
 * is violated.
 * 
 * 
 * @version $Revision: 618057 $ $Date: 2008-02-03 11:58:54 -0700 (Sun, 03 Feb
 *          2008) $
 */
public class ResizableDoubleArray implements Serializable {
  /** Serializable version identifier */
  private static final long serialVersionUID = -3485529955529426875L;
  /** additive expansion mode */
  public static final int ADDITIVE_MODE = 1;
  /** multiplicative expansion mode */
  public static final int MULTIPLICATIVE_MODE = 0;
  /**
   * The contraction criteria determines when the internal array will be
   * contracted to fit the number of elements contained in the element array +
   * 1.
   */
  protected float contractionCriteria = 2.5f;
  /**
   * The expansion factor of the array. When the array needs to be expanded, the
   * new array size will be <code>internalArray.length * expansionFactor</code>
   * if <code>expansionMode</code> is set to MULTIPLICATIVE_MODE, or
   * <code>internalArray.length + expansionFactor</code> if
   * <code>expansionMode</code> is set to ADDITIVE_MODE.
   */
  protected float expansionFactor = 2.0f;
  /**
   * Determines whether array expansion by <code>expansionFactor</code> is
   * additive or multiplicative.
   */
  protected int expansionMode = MULTIPLICATIVE_MODE;
  /**
   * The initial capacity of the array. Initial capacity is not exposed as a
   * property as it is only meaningful when passed to a constructor.
   */
  protected int initialCapacity = 16;
  /**
   * The internal storage array.
   */
  protected double[] internalArray;
  /**
   * The number of addressable elements in the array. Note that this has nothing
   * to do with the length of the internal storage array.
   */
  protected int numElements = 0;
  /**
   * The position of the first addressable element in the internal storage
   * array. The addressable elements in the array are <code>
   * internalArray[startIndex],...,internalArray[startIndex + numElements -1]
   * </code>
   */
  protected int startIndex = 0;
  /**
   * Create a ResizableArray with default properties.
   * <ul>
   * <li><code>initialCapacity = 16</code></li>
   * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
   * <li><code>expansionFactor = 2.5</code></li>
   * <li><code>contractionFactor = 2.0</code></li>
   * </ul>
   */
  public ResizableDoubleArray() {
    internalArray = new double[initialCapacity];
  }
  /**
   * Create a ResizableArray with the specified initial capacity. Other
   * properties take default values:
   * <ul>
   * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
   * <li><code>expansionFactor = 2.5</code></li>
   * <li><code>contractionFactor = 2.0</code></li>
   * </ul>
   * 
   * @param initialCapacity
   *          The initial size of the internal storage array
   * @throws IllegalArgumentException
   *           if initialCapacity is not > 0
   */
  public ResizableDoubleArray(int initialCapacity) {
    setInitialCapacity(initialCapacity);
    internalArray = new double[this.initialCapacity];
  }
  /**
   * 
   * Create a ResizableArray with the specified initial capacity and expansion
   * factor. The remaining properties take default values:
   * <ul>
   * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
   * <li><code>contractionFactor = 0.5 + expansionFactor</code></li>
   * </ul>
   * 
   * 
   * Throws IllegalArgumentException if the following conditions are not met:
   * <ul>
   * <li><code>initialCapacity > 0</code></li>
   * <li><code>expansionFactor > 1</code></li>
   * </ul>
   * 
   * 
   * @param initialCapacity
   *          The initial size of the internal storage array
   * @param expansionFactor
   *          the array will be expanded based on this parameter
   * @throws IllegalArgumentException
   *           if parameters are not valid
   */
  public ResizableDoubleArray(int initialCapacity, float expansionFactor) {
    this.expansionFactor = expansionFactor;
    setInitialCapacity(initialCapacity);
    internalArray = new double[initialCapacity];
    setContractionCriteria(expansionFactor + 0.5f);
  }
  /**
   * 
   * Create a ResizableArray with the specified initialCapacity,
   * expansionFactor, and contractionCriteria. The <code>expansionMode</code>
   * will default to <code>MULTIPLICATIVE_MODE.</code>
   * 
   * 
   * Throws IllegalArgumentException if the following conditions are not met:
   * <ul>
   * <li><code>initialCapacity > 0</code></li>
   * <li><code>expansionFactor > 1</code></li>
   * <li><code>contractionFactor >= expansionFactor</code></li>
   * </ul>
   * 
   * 
   * @param initialCapacity
   *          The initial size of the internal storage array
   * @param expansionFactor
   *          the array will be expanded based on this parameter
   * @param contractionCriteria
   *          The contraction Criteria.
   * @throws IllegalArgumentException
   *           if parameters are not valid
   */
  public ResizableDoubleArray(int initialCapacity, float expansionFactor, float contractionCriteria) {
    this.expansionFactor = expansionFactor;
    setContractionCriteria(contractionCriteria);
    setInitialCapacity(initialCapacity);
    internalArray = new double[initialCapacity];
  }
  /**
   * 
   * Create a ResizableArray with the specified properties.
   * 
   * 
   * Throws IllegalArgumentException if the following conditions are not met:
   * <ul>
   * <li><code>initialCapacity > 0</code></li>
   * <li><code>expansionFactor > 1</code></li>
   * <li><code>contractionFactor >= expansionFactor</code></li>
   * <li><code>expansionMode in {MULTIPLICATIVE_MODE, ADDITIVE_MODE}</code>
   * </li>
   * </ul>
   * 
   * 
   * @param initialCapacity
   *          the initial size of the internal storage array
   * @param expansionFactor
   *          the array will be expanded based on this parameter
   * @param contractionCriteria
   *          the contraction Criteria
   * @param expansionMode
   *          the expansion mode
   * @throws IllegalArgumentException
   *           if parameters are not valid
   */
  public ResizableDoubleArray(int initialCapacity, float expansionFactor,
      float contractionCriteria, int expansionMode) {
    this.expansionFactor = expansionFactor;
    setContractionCriteria(contractionCriteria);
    setInitialCapacity(initialCapacity);
    setExpansionMode(expansionMode);
    internalArray = new double[initialCapacity];
  }
  /**
   * Adds an element to the end of this expandable array.
   * 
   * @param value
   *          to be added to end of array
   */
  public synchronized void addElement(double value) {
    numElements++;
    if ((startIndex + numElements) > internalArray.length) {
      expand();
    }
    internalArray[startIndex + (numElements - 1)] = value;
    if (shouldContract()) {
      contract();
    }
  }
  /**
   * 
   * Adds an element to the end of the array and removes the first element in
   * the array. Returns the discarded first element. The effect is similar to a
   * push operation in a FIFO queue.
   * 
   * 
   * Example: If the array contains the elements 1, 2, 3, 4 (in that order) and
   * addElementRolling(5) is invoked, the result is an array containing the
   * entries 2, 3, 4, 5 and the value returned is 1.
   * 
   * 
   * @param value
   *          the value to be added to the array
   * @return the value which has been discarded or "pushed" out of the array by
   *         this rolling insert
   */
  public synchronized double addElementRolling(double value) {
    double discarded = internalArray[startIndex];
    if ((startIndex + (numElements + 1)) > internalArray.length) {
      expand();
    }
    // Increment the start index
    startIndex += 1;
    // Add the new value
    internalArray[startIndex + (numElements - 1)] = value;
    // Check the contraction criteria
    if (shouldContract()) {
      contract();
    }
    return discarded;
  }
  /**
   * Checks the expansion factor and the contraction criteria and throws an
   * IllegalArgumentException if the contractionCriteria is less than the
   * expansionCriteria
   * 
   * @param expansionFactor
   *          factor to be checked
   * @param contractionCritera
   *          critera to be checked
   * @throws IllegalArgumentException
   *           if the contractionCriteria is less than the expansionCriteria.
   */
  protected void checkContractExpand(float contractionCritera, float expansionFactor) {
    if (contractionCritera < expansionFactor) {
      String msg = "Contraction criteria can never be smaller than "
          + "the expansion factor.  This would lead to a never "
          + "ending loop of expansion and contraction as a newly "
          + "expanded internal storage array would immediately "
          + "satisfy the criteria for contraction";
      throw new IllegalArgumentException(msg);
    }
    if (contractionCriteria <= 1.0) {
      String msg = "The contraction criteria must be a number larger "
          + "than one.  If the contractionCriteria is less than or "
          + "equal to one an endless loop of contraction and "
          + "expansion would ensue as an internalArray.length "
          + "== numElements would satisfy the contraction criteria";
      throw new IllegalArgumentException(msg);
    }
    if (expansionFactor <= 1.0) {
      String msg = "The expansion factor must be a number greater than 1.0";
      throw new IllegalArgumentException(msg);
    }
  }
  /**
   * Clear the array, reset the size to the initialCapacity and the number of
   * elements to zero.
   */
  public synchronized void clear() {
    numElements = 0;
    internalArray = new double[initialCapacity];
  }
  /**
   * Contracts the storage array to the (size of the element set) + 1 - to avoid
   * a zero length array. This function also resets the startIndex to zero.
   */
  public synchronized void contract() {
    double[] tempArray = new double[numElements + 1];
    // Copy and swap - copy only the element array from the src array.
    System.arraycopy(internalArray, startIndex, tempArray, 0, numElements);
    internalArray = tempArray;
    // Reset the start index to zero
    startIndex = 0;
  }
  /**
   * Discards the <code>i<code> initial elements of the array.  For example,
   * if the array contains the elements 1,2,3,4, invoking 
   * <code>discardFrontElements(2)</code> will cause the first two elements 
   * to be discarded, leaving 3,4 in the array.  Throws illegalArgumentException
   * if i exceeds numElements.
   * 
   * @param i  the number of elements to discard from the front of the array
   * @throws IllegalArgumentException if i is greater than numElements.
   */
  public synchronized void discardFrontElements(int i) {
    if (i > numElements) {
      String msg = "Cannot discard more elements than are" + "contained in this array.";
      throw new IllegalArgumentException(msg);
    } else if (i < 0) {
      String msg = "Cannot discard a negative number of elements.";
      throw new IllegalArgumentException(msg);
    } else {
      // "Subtract" this number of discarded from numElements
      numElements -= i;
      startIndex += i;
    }
    if (shouldContract()) {
      contract();
    }
  }
  /**
   * Expands the internal storage array using the expansion factor.
   * 
   * if <code>expansionMode</code> is set to MULTIPLICATIVE_MODE, the new
   * array size will be <code>internalArray.length * expansionFactor.</code>
   * If <code>expansionMode</code> is set to ADDITIVE_MODE, the length after
   * expansion will be <code>internalArray.length + expansionFactor</code>
   * 
   */
  protected synchronized void expand() {
    // notice the use of Math.ceil(), this gaurantees that we will always
    // have an array of at least currentSize + 1. Assume that the
    // current initial capacity is 1 and the expansion factor
    // is 1.000000000000000001. The newly calculated size will be
    // rounded up to 2 after the multiplication is performed.
    int newSize = 0;
    if (expansionMode == MULTIPLICATIVE_MODE) {
      newSize = (int) Math.ceil(internalArray.length * expansionFactor);
    } else {
      newSize = internalArray.length + Math.round(expansionFactor);
    }
    double[] tempArray = new double[newSize];
    // Copy and swap
    System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length);
    internalArray = tempArray;
  }
  /**
   * Expands the internal storage array to the specified size.
   * 
   * @param size
   *          Size of the new internal storage array
   */
  private synchronized void expandTo(int size) {
    double[] tempArray = new double[size];
    // Copy and swap
    System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length);
    internalArray = tempArray;
  }
  /**
   * The contraction criteria defines when the internal array will contract to
   * store only the number of elements in the element array. If the
   * <code>expansionMode</code> is <code>MULTIPLICATIVE_MODE</code>,
   * contraction is triggered when the ratio between storage array length and
   * <code>numElements</code> exceeds <code>contractionFactor</code>. If
   * the <code>expansionMode</code> is <code>ADDITIVE_MODE</code>, the
   * number of excess storage locations is compared to
   * <code>contractionFactor.</code>
   * 
   * @return the contraction criteria used to reclaim memory.
   */
  public float getContractionCriteria() {
    return contractionCriteria;
  }
  /**
   * Returns the element at the specified index
   * 
   * @param index
   *          index to fetch a value from
   * @return value stored at the specified index
   * @throws ArrayIndexOutOfBoundsException
   *           if <code>index</code> is less than zero or is greater than
   *           <code>getNumElements() - 1</code>.
   */
  public synchronized double getElement(int index) {
    if (index >= numElements) {
      String msg = "The index specified: " + index
          + " is larger than the current number of elements";
      throw new ArrayIndexOutOfBoundsException(msg);
    } else if (index >= 0) {
      return internalArray[startIndex + index];
    } else {
      String msg = "Elements cannot be retrieved from a negative array index";
      throw new ArrayIndexOutOfBoundsException(msg);
    }
  }
  /**
   * Returns a double array containing the elements of this
   * <code>ResizableArray</code>. This method returns a copy, not a reference
   * to the underlying array, so that changes made to the returned array have no
   * effect on this <code>ResizableArray.</code>
   * 
   * @return the double array.
   */
  public synchronized double[] getElements() {
    double[] elementArray = new double[numElements];
    System.arraycopy(internalArray, startIndex, elementArray, 0, numElements);
    return elementArray;
  }
  /**
   * The expansion factor controls the size of a new aray when an array needs to
   * be expanded. The <code>expansionMode</code> determines whether the size
   * of the array is multiplied by the <code>expansionFactor</code>
   * (MULTIPLICATIVE_MODE) or if the expansion is additive (ADDITIVE_MODE --
   * <code>expansionFactor</code> storage locations added). The default
   * <code>expansionMode</code> is MULTIPLICATIVE_MODE and the default
   * <code>expansionFactor</code> is 2.0.
   * 
   * @return the expansion factor of this expandable double array
   */
  public float getExpansionFactor() {
    return expansionFactor;
  }
  /**
   * The <code>expansionMode</code> determines whether the internal storage
   * array grows additively (ADDITIVE_MODE) or multiplicatively
   * (MULTIPLICATIVE_MODE) when it is expanded.
   * 
   * @return Returns the expansionMode.
   */
  public int getExpansionMode() {
    return expansionMode;
  }
  /**
   * Notice the package scope on this method. This method is simply here for the
   * JUnit test, it allows us check if the expansion is working properly after a
   * number of expansions. This is not meant to be a part of the public
   * interface of this class.
   * 
   * @return the length of the internal storage array.
   */
  synchronized int getInternalLength() {
    return (internalArray.length);
  }
  /**
   * Returns the number of elements currently in the array. Please note that
   * this is different from the length of the internal storage array.
   * 
   * @return number of elements
   */
  public synchronized int getNumElements() {
    return (numElements);
  }
  /**
   * Returns the internal storage array. Note that this method returns a
   * reference to the internal storage array, not a copy, and to correctly
   * address elements of the array, the <code>startIndex</code> is required
   * (available via the {@link #start} method). This method should only be used
   * in cases where copying the internal array is not practical. The
   * {@link #getElements} method should be used in all other cases.
   * 
   * 
   * @return the internal storage array used by this object
   */
  public synchronized double[] getValues() {
    return (internalArray);
  }
  /**
   * Sets the contraction criteria for this ExpandContractDoubleArray.
   * 
   * @param contractionCriteria
   *          contraction criteria
   */
  public void setContractionCriteria(float contractionCriteria) {
    checkContractExpand(contractionCriteria, getExpansionFactor());
    this.contractionCriteria = contractionCriteria;
  }
  /**
   * Sets the element at the specified index. If the specified index is greater
   * than <code>getNumElements() - 1</code>, the <code>numElements</code>
   * property is increased to <code>index +1</code> and additional storage is
   * allocated (if necessary) for the new element and all (uninitialized)
   * elements between the new element and the previous end of the array).
   * 
   * @param index
   *          index to store a value in
   * @param value
   *          value to store at the specified index
   * @throws ArrayIndexOutOfBoundsException
   *           if <code>index</code> is less than zero.
   */
  public synchronized void setElement(int index, double value) {
    if (index < 0) {
      String msg = "Cannot set an element at a negative index";
      throw new ArrayIndexOutOfBoundsException(msg);
    }
    if (index + 1 > numElements) {
      numElements = index + 1;
    }
    if ((startIndex + index) >= internalArray.length) {
      expandTo(startIndex + (index + 1));
    }
    internalArray[startIndex + index] = value;
  }
  /**
   * Sets the expansionFactor. Throws IllegalArgumentException if the the
   * following conditions are not met:
   * <ul>
   * <li><code>expansionFactor > 1</code></li>
   * <li><code>contractionFactor >= expansionFactor</code></li>
   * </ul>
   * 
   * @param expansionFactor
   *          the new expansion factor value.
   * @throws IllegalArgumentException
   *           if expansionFactor is <= 1 or greater than contractionFactor
   */
  public void setExpansionFactor(float expansionFactor) {
    checkContractExpand(getContractionCriteria(), expansionFactor);
    // The check above verifies that the expansion factor is > 1.0;
    this.expansionFactor = expansionFactor;
  }
  /**
   * Sets the <code>expansionMode</code>. The specified value must be one of
   * ADDITIVE_MODE, MULTIPLICATIVE_MODE.
   * 
   * @param expansionMode
   *          The expansionMode to set.
   * @throws IllegalArgumentException
   *           if the specified mode value is not valid
   */
  public void setExpansionMode(int expansionMode) {
    if (expansionMode != MULTIPLICATIVE_MODE && expansionMode != ADDITIVE_MODE) {
      throw new IllegalArgumentException("Illegal expansionMode setting.");
    }
    this.expansionMode = expansionMode;
  }
  /**
   * Sets the initial capacity. Should only be invoked by constructors.
   * 
   * @param initialCapacity
   *          of the array
   * @throws IllegalArgumentException
   *           if <code>initialCapacity</code> is not positive.
   */
  protected void setInitialCapacity(int initialCapacity) {
    if (initialCapacity > 0) {
      synchronized (this) {
        this.initialCapacity = initialCapacity;
      }
    } else {
      String msg = "The initial capacity supplied: " + initialCapacity
          + "must be a positive integer";
      throw new IllegalArgumentException(msg);
    }
  }
  /**
   * This function allows you to control the number of elements contained in
   * this array, and can be used to "throw out" the last n values in an array.
   * This function will also expand the internal array as needed.
   * 
   * @param i
   *          a new number of elements
   * @throws IllegalArgumentException
   *           if <code>i</code> is negative.
   */
  public synchronized void setNumElements(int i) {
    // If index is negative thrown an error
    if (i < 0) {
      String msg = "Number of elements must be zero or a positive " + "integer";
      throw new IllegalArgumentException(msg);
    }
    // Test the new num elements, check to see if the array needs to be
    // expanded to accomodate this new number of elements
    if ((startIndex + i) > internalArray.length) {
      expandTo(startIndex + i);
    }
    // Set the new number of elements to new value
    numElements = i;
  }
  /**
   * Returns true if the internal storage array has too many unused storage
   * positions.
   * 
   * @return true if array satisfies the contraction criteria
   */
  private synchronized boolean shouldContract() {
    if (expansionMode == MULTIPLICATIVE_MODE) {
      return (internalArray.length / ((float) numElements)) > contractionCriteria;
    } else {
      return (internalArray.length - numElements) > contractionCriteria;
    }
  }
  /**
   * Returns the starting index of the internal array. The starting index is the
   * position of the first addressable element in the internal storage array.
   * The addressable elements in the array are <code>
   * internalArray[startIndex],...,internalArray[startIndex + numElements -1]
   * </code>
   * 
   * @return starting index
   */
  public synchronized int start() {
    return startIndex;
  }
}





A writer for char strings

/* Copyright (c) 2001-2009, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * A writer for char strings.
 * 
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @version 1.9.0
 * @since 1.9.0
 */
public class CharArrayWriter {
  protected char[] buffer;
  protected int count;
  public CharArrayWriter(char[] buffer) {
    this.buffer = buffer;
  }
  public void write(int c) {
    if (count == buffer.length) {
      ensureSize(count + 1);
    }
    buffer[count++] = (char) c;
  }
  void ensureSize(int size) {
    if (size <= buffer.length) {
      return;
    }
    int newSize = buffer.length;
    while (newSize < size) {
      newSize *= 2;
    }
    char[] newBuffer = new char[newSize];
    System.arraycopy(buffer, 0, newBuffer, 0, count);
    buffer = newBuffer;
  }
  public void write(String str, int off, int len) {
    ensureSize(count + len);
    str.getChars(off, off + len, buffer, count);
    count += len;
  }
  public void reset() {
    count = 0;
  }
  public void reset(char[] buffer) {
    count = 0;
    this.buffer = buffer;
  }
  public char[] toCharArray() {
    char[] newBuffer = new char[count];
    System.arraycopy(buffer, 0, newBuffer, 0, count);
    return (char[]) newBuffer;
  }
  public int size() {
    return count;
  }
  /**
   * Converts input data to a string.
   * 
   * @return the string.
   */
  public String toString() {
    return new String(buffer, 0, count);
  }
}





ByteArray wraps java byte arrays (byte[]) to allow byte arrays to be used as keys in hashtables.

/*
   Derby - Class org.apache.derby.iapi.util.ByteArray
   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.
 */

import java.io.ObjectOutput;
import java.io.ObjectInput;
import java.io.IOException;
/**
  ByteArray wraps java byte arrays (byte[]) to allow
  byte arrays to be used as keys in hashtables.
  This is required because the equals function on
  byte[] directly uses reference equality.
  
  This class also allows the trio of array, offset and length
  to be carried around as a single object.
*/
public final class ByteArray
{
  private byte[] array;
  private int    offset;
  private int    length;
  /**
    Create an instance of this class that wraps ths given array.
    This class does not make a copy of the array, it just saves
    the reference.
  */
  public ByteArray(byte[] array, int offset, int length) {
    this.array = array;
    this.offset = offset;
    this.length = length;
  }
  public ByteArray(byte[] array) {
    this(array, 0, array.length);
  }
  public ByteArray()
  {
  }
  public void setBytes(byte[] array)
  {
    this.array = array;
    offset = 0;
    length = array.length;
  } 
  public void setBytes(byte[] array, int length)
  {
    this.array = array;
    this.offset = 0;
    this.length = length;
  } 
  public void setBytes(byte[] array, int offset, int length)
  {
    this.array = array;
    this.offset = offset;
    this.length = length;
  } 

  /**
    Value equality for byte arrays.
  */
  public boolean equals(Object other) {
    if (other instanceof ByteArray) {
      ByteArray ob = (ByteArray) other;
      return ByteArray.equals(array, offset, length, ob.array, ob.offset, ob.length);
    }
    return false;
  }

  /**
  */
  public int hashCode() {
    byte[] larray = array;
    int hash = length;
    for (int i = 0; i < length; i++) {
      hash += larray[i + offset];
    }
    return hash;
  }
  public final byte[] getArray() {
    return array;
  }
  public final int getOffset() {
    return offset;
  }
  public final int getLength() {
    return length;
  }
  public final void setLength(int newLength) {
    length = newLength;
  }
  
  /**
   * Read this object from a stream of stored objects.
   *
   * @param in read this.
   *
   * @exception IOException         thrown on error
   */
  public void readExternal( ObjectInput in ) throws IOException
  {
    int len = length = in.readInt();
    offset = 0; 
    array = new byte[len];
    in.readFully(array, 0, len);
  }

  /**
   * Write the byte array out w/o compression
   *
   * @param out write bytes here.
   *
   * @exception IOException   thrown on error
   */
  public void writeExternal(ObjectOutput out) throws IOException
  {
    out.writeInt(length);
    out.write(array, offset, length);
  }

  /**
    Compare two byte arrays using value equality.
    Two byte arrays are equal if their length is
    identical and their contents are identical.
  */
  private static boolean equals(byte[] a, int aOffset, int aLength, byte[] b, int bOffset, int bLength) {
    if (aLength != bLength)
      return false;
    for (int i = 0; i < aLength; i++) {
      if (a[i + aOffset] != b[i + bOffset])
        return false;
    }
    return true;
  }
}





Concatenates two arrays of strings

/*
 * Copyright 2000,2005 wingS development team.
 *
 * This file is part of wingS (http://wingsframework.org).
 *
 * wingS 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.
 *
 * Please see COPYING for the complete licence.
 */
import java.util.StringTokenizer;
/**
 * Some string manipulation utilities.
 *
 * @author 
 */
public class StringUtil {
  /**
   * concatenates two arrays of strings.
   *
   * @param s1 the first array of strings.
   * @param s2 the second array of strings.
   * @return the resulting array with all strings in s1 and s2
   */
  public static final String[] concat(String[] s1, String[] s2) {
      String[] erg = new String[s1.length + s2.length];
      System.arraycopy(s1, 0, erg, 0, s1.length);
      System.arraycopy(s2, 0, erg, s1.length, s2.length);
      return erg;
  }
  
}





Lazy List creation

import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
// Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed 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.

/* ------------------------------------------------------------ */
/** Lazy List creation.
 * A List helper class that attempts to avoid unneccessary List
 * creation.   If a method needs to create a List to return, but it is
 * expected that this will either be empty or frequently contain a
 * single item, then using LazyList will avoid additional object
 * creations by using Collections.EMPTY_LIST or
 * Collections.singletonList where possible.
 *
 * <h4>Usage</h4>
 * <pre>
 *   Object lazylist =null;
 *   while(loopCondition)
 *   {
 *     Object item = getItem();
 *     if (item.isToBeAdded())
 *         lazylist = LazyList.add(lazylist,item);
 *   }
 *   return LazyList.getList(lazylist);
 * </pre>
 *
 * An ArrayList of default size is used as the initial LazyList.
 *
 * @see java.util.List
 * @author Greg Wilkins (gregw)
 */
class LazyList
    implements Cloneable, Serializable
{
    private static final String[] __EMTPY_STRING_ARRAY = new String[0];
    
    /* ------------------------------------------------------------ */
    private LazyList()
    {}
    
    /* ------------------------------------------------------------ */
    /** Add an item to a LazyList 
     * @param list The list to add to or null if none yet created.
     * @param item The item to add.
     * @return The lazylist created or added to.
     */
    public static Object add(Object list, Object item)
    {
        if (list==null)
        {
            if (item instanceof List || item==null)
            {
                List l = new ArrayList();
                l.add(item);
                return l;
            }
            return item;
        }
        if (list instanceof List)
        {
            ((List)list).add(item);
            return list;
        }
        List l=new ArrayList();
        l.add(list);
        l.add(item);
        return l;    
    }
    /* ------------------------------------------------------------ */
    /** Add an item to a LazyList 
     * @param list The list to add to or null if none yet created.
     * @param index The index to add the item at.
     * @param item The item to add.
     * @return The lazylist created or added to.
     */
    public static Object add(Object list, int index, Object item)
    {
        if (list==null)
        {
            if (index>0 || item instanceof List || item==null)
            {
                List l = new ArrayList();
                l.add(index,item);
                return l;
            }
            return item;
        }
        if (list instanceof List)
        {
            ((List)list).add(index,item);
            return list;
        }
        List l=new ArrayList();
        l.add(list);
        l.add(index,item);
        return l;    
    }
    
    /* ------------------------------------------------------------ */
    /** Add the contents of a Collection to a LazyList
     * @param list The list to add to or null if none yet created.
     * @param collection The Collection whose contents should be added.
     * @return The lazylist created or added to.
     */
    public static Object addCollection(Object list, Collection collection)
    {
        Iterator i=collection.iterator();
        while(i.hasNext())
            list=LazyList.add(list,i.next());
        return list;
    }
    
    /* ------------------------------------------------------------ */
    /** Add the contents of an array to a LazyList
     * @param list The list to add to or null if none yet created.
     * @param collection The Collection whose contents should be added.
     * @return The lazylist created or added to.
     */
    public static Object addArray(Object list, Object[] array)
    {
        for(int i=0;array!=null && i<array.length;i++)
            list=LazyList.add(list,array[i]);
        return list;
    }
    /* ------------------------------------------------------------ */
    /** Ensure the capcity of the underlying list.
     * 
     */
    public static Object ensureSize(Object list, int initialSize)
    {
        if (list==null)
            return new ArrayList(initialSize);
        if (list instanceof ArrayList)
        {
            ArrayList ol=(ArrayList)list;
            if (ol.size()>initialSize)
                return ol;
            ArrayList nl = new ArrayList(initialSize);
            nl.addAll(ol);
            return nl;
        }
        List l= new ArrayList(initialSize);
        l.add(list);
        return l;    
    }
    /* ------------------------------------------------------------ */
    public static Object remove(Object list, Object o)
    {
        if (list==null)
            return null;
        if (list instanceof List)
        {
            List l = (List)list;
            l.remove(o);
            if (l.size()==0)
                return null;
            return list;
        }
        if (list.equals(o))
            return null;
        return list;
    }
    
    /* ------------------------------------------------------------ */
    public static Object remove(Object list, int i)
    {
        if (list==null)
            return null;
        if (list instanceof List)
        {
            List l = (List)list;
            l.remove(i);
            if (l.size()==0)
                return null;
            return list;
        }
        if (i==0)
            return null;
        return list;
    }
    
    
    
    /* ------------------------------------------------------------ */
    /** Get the real List from a LazyList.
     * 
     * @param list A LazyList returned from LazyList.add(Object)
     * @return The List of added items, which may be an EMPTY_LIST
     * or a SingletonList.
     */
    public static List getList(Object list)
    {
        return getList(list,false);
    }
    
    /* ------------------------------------------------------------ */
    /** Get the real List from a LazyList.
     * 
     * @param list A LazyList returned from LazyList.add(Object) or null
     * @param nullForEmpty If true, null is returned instead of an
     * empty list.
     * @return The List of added items, which may be null, an EMPTY_LIST
     * or a SingletonList.
     */
    public static List getList(Object list, boolean nullForEmpty)
    {
        if (list==null)
            return nullForEmpty?null:Collections.EMPTY_LIST;
        if (list instanceof List)
            return (List)list;
        
        List l = new ArrayList(1);
        l.add(list);
        return l;
    }
    
    /* ------------------------------------------------------------ */
    public static String[] toStringArray(Object list)
    {
        if (list==null)
            return __EMTPY_STRING_ARRAY;
        
        if (list instanceof List)
        {
            List l = (List)list;
            String[] a = new String[l.size()];
            for (int i=l.size();i-->0;)
            {
                Object o=l.get(i);
                if (o!=null)
                    a[i]=o.toString();
            }
            return a;
        }
        
        return new String[] {list.toString()};
    }
    /* ------------------------------------------------------------ */
    public static Object toArray(Object list,Class aClass)
    {
        if (list==null)
            return (Object[])Array.newInstance(aClass,0);
        
        if (list instanceof List)
        {
            List l = (List)list;
            if (aClass.isPrimitive())
            {
                Object a = Array.newInstance(aClass,l.size());
                for (int i=0;i<l.size();i++)
                    Array.set(a,i,l.get(i));
                return a;
            }
            return l.toArray((Object[])Array.newInstance(aClass,l.size()));
            
        }
        
        Object a = Array.newInstance(aClass,1);
        Array.set(a,0,list);
        return a;
    }
    /* ------------------------------------------------------------ */
    /** The size of a lazy List 
     * @param list  A LazyList returned from LazyList.add(Object) or null
     * @return the size of the list.
     */
    public static int size(Object list)
    {
        if (list==null)
            return 0;
        if (list instanceof List)
            return ((List)list).size();
        return 1;
    }
    
    /* ------------------------------------------------------------ */
    /** Get item from the list 
     * @param list  A LazyList returned from LazyList.add(Object) or null
     * @param i int index
     * @return the item from the list.
     */
    public static Object get(Object list, int i)
    {
        if (list==null)
            throw new IndexOutOfBoundsException();
        
        if (list instanceof List)
            return ((List)list).get(i);
        if (i==0)
            return list;
        
        throw new IndexOutOfBoundsException();
    }
    
    /* ------------------------------------------------------------ */
    public static boolean contains(Object list,Object item)
    {
        if (list==null)
            return false;
        
        if (list instanceof List)
            return ((List)list).contains(item);
        return list.equals(item);
    }
    
    /* ------------------------------------------------------------ */
    public static Object clone(Object list)
    {
        if (list==null)
            return null;
        if (list instanceof List)
            return new ArrayList((List)list);
        return list;
    }
    
    /* ------------------------------------------------------------ */
    public static String toString(Object list)
    {
        if (list==null)
            return "[]";
        if (list instanceof List)
            return ((List)list).toString();
        return "["+list+"]";
    }
    /* ------------------------------------------------------------ */
    public static Iterator iterator(Object list)
    {
        if (list==null)
            return Collections.EMPTY_LIST.iterator();
        if (list instanceof List)
            return ((List)list).iterator();
        return getList(list).iterator();
    }
    
    /* ------------------------------------------------------------ */
    public static ListIterator listIterator(Object list)
    {
        if (list==null)
            return Collections.EMPTY_LIST.listIterator();
        if (list instanceof List)
            return ((List)list).listIterator();
        return getList(list).listIterator();
    }
    /* ------------------------------------------------------------ */
    /**
     * @param array Any array of object
     * @return A new <i>modifiable</i> list initialised with the elements from <code>array</code>.
     */
    public static List array2List(Object[] array)
    { 
        if (array==null || array.length==0)
            return new ArrayList();
        return new ArrayList(Arrays.asList(array));
    }
    /* ------------------------------------------------------------ */
    /** Add element to an array
     * @param array The array to add to (or null)
     * @param item The item to add
     * @param type The type of the array (in case of null array)
     * @return new array with contents of array plus item
     */
    public static Object[] addToArray(Object[] array, Object item, Class type)
    {
        if (array==null)
        {
            if (type==null && item!=null)
                type= item.getClass();
            Object[] na = (Object[])Array.newInstance(type, 1);
            na[0]=item;
            return na;
        }
        else
        {
            Class c = array.getClass().getComponentType();
            Object[] na = (Object[])Array.newInstance(c, Array.getLength(array)+1);
            System.arraycopy(array, 0, na, 0, array.length);
            na[array.length]=item;
            return na;
        }
    }
    /* ------------------------------------------------------------ */
    public static Object[] removeFromArray(Object[] array, Object item)
    {
        if (item==null || array==null)
            return array;
        for (int i=array.length;i-->0;)
        {
            if (item.equals(array[i]))
            {
                Class c = array==null?item.getClass():array.getClass().getComponentType();
                Object[] na = (Object[])Array.newInstance(c, Array.getLength(array)-1);
                if (i>0)
                    System.arraycopy(array, 0, na, 0, i);
                if (i+1<array.length)
                    System.arraycopy(array, i+1, na, i, array.length-(i+1));
                return na;
            }
        }
        return array;
    }
    
}





Puts the entire source array in the target array at offset offset.

/*
 * Copyright Aduna (http://www.aduna-software.ru/) (c) 1997-2006.
 *
 * Licensed under the Aduna BSD-style license.
 */

public class Utils {

  /**
   * Puts the entire <tt>source</tt> array in the <tt>target</tt>
   * array at offset <tt>offset</tt>.
   */
  public static void put(byte[] source, byte[] target, int offset) {
    System.arraycopy(source, 0, target, offset, source.length);
  }

}





Simple object pool

/*
 *  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.
 */

/**
 * Simple object pool. Based on ThreadPool and few other classes
 * 
 * The pool will ignore overflow and return null if empty.
 * 
 * @author Gal Shachor
 * @author Costin Manolache
 */
public final class SimplePool {
  /*
   * Where the threads are held.
   */
  private Object pool[];
  private int max;
  private int last;
  private int current = -1;
  private Object lock;
  public static final int DEFAULT_SIZE = 32;
  static final int debug = 0;
  public SimplePool() {
    this(DEFAULT_SIZE, DEFAULT_SIZE);
  }
  public SimplePool(int size) {
    this(size, size);
  }
  public SimplePool(int size, int max) {
    this.max = max;
    pool = new Object[size];
    this.last = size - 1;
    lock = new Object();
  }
  public void set(Object o) {
    put(o);
  }
  /**
   * Add the object to the pool, silent nothing if the pool is full
   */
  public void put(Object o) {
    synchronized (lock) {
      if (current < last) {
        current++;
        pool[current] = o;
      } else if (current < max) {
        // realocate
        int newSize = pool.length * 2;
        if (newSize > max)
          newSize = max + 1;
        Object tmp[] = new Object[newSize];
        last = newSize - 1;
        System.arraycopy(pool, 0, tmp, 0, pool.length);
        pool = tmp;
        current++;
        pool[current] = o;
      }
    }
  }
  /**
   * Get an object from the pool, null if the pool is empty.
   */
  public Object get() {
    Object item = null;
    synchronized (lock) {
      if (current >= 0) {
        item = pool[current];
        pool[current] = null;
        current -= 1;
      }
    }
    return item;
  }
  /**
   * Return the size of the pool
   */
  public int getMax() {
    return max;
  }
  /**
   * Number of object in the pool
   */
  public int getCount() {
    return current + 1;
  }
  public void shutdown() {
  }
}





Simple object pool. Based on ThreadPool and few other classes

/*
 * 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.    
 */
/**
 * Simple object pool. Based on ThreadPool and few other classes
 * 
 * The pool will ignore overflow and return null if empty.
 * 
 * @author Gal Shachor
 * @author Costin
 * @author 
 * @version $Id: SimplePool.java 463298 2006-10-12 16:10:32Z henning $
 */
public final class SimplePool {
  /*
   * Where the objects are held.
   */
  private Object pool[];
  /**
   * max amount of objects to be managed set via CTOR
   */
  private int max;
  /**
   * index of previous to next free slot
   */
  private int current = -1;
  /**
   * @param max
   */
  public SimplePool(int max) {
    this.max = max;
    pool = new Object[max];
  }
  /**
   * Add the object to the pool, silent nothing if the pool is full
   * 
   * @param o
   */
  public void put(Object o) {
    int idx = -1;
    synchronized (this) {
      /*
       * if we aren"t full
       */
      if (current < max - 1) {
        /*
         * then increment the current index.
         */
        idx = ++current;
      }
      if (idx >= 0) {
        pool[idx] = o;
      }
    }
  }
  /**
   * Get an object from the pool, null if the pool is empty.
   * 
   * @return The object from the pool.
   */
  public Object get() {
    synchronized (this) {
      /*
       * if we have any in the pool
       */
      if (current >= 0) {
        /*
         * remove the current one
         */
        Object o = pool[current];
        pool[current] = null;
        current--;
        return o;
      }
    }
    return null;
  }
  /**
   * Return the size of the pool
   * 
   * @return The pool size.
   */
  public int getMax() {
    return max;
  }
  /**
   * for testing purposes, so we can examine the pool
   * 
   * @return Array of Objects in the pool.
   */
  Object[] getPool() {
    return pool;
  }
}





Stores a list of int

/*
 * 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.
 */
/*
 * $Id: IntVector.java 468655 2006-10-28 07:12:06Z minchau $
 */
/**
 * A very simple table that stores a list of int.
 *
 * This version is based on a "realloc" strategy -- a simle array is
 * used, and when more storage is needed, a larger array is obtained
 * and all existing data is recopied into it. As a result, read/write
 * access to existing nodes is O(1) fast but appending may be O(N**2)
 * slow. See also SuballocatedIntVector.
 * @xsl.usage internal
 */
public class IntVector implements Cloneable
{
  /** Size of blocks to allocate          */
  protected int m_blocksize;
  /** Array of ints          */
  protected int m_map[]; // IntStack is trying to see this directly
  /** Number of ints in array          */
  protected int m_firstFree = 0;
  /** Size of array          */
  protected int m_mapSize;
  /**
   * Default constructor.  Note that the default
   * block size is very small, for small lists.
   */
  public IntVector()
  {
    m_blocksize = 32;
    m_mapSize = m_blocksize;
    m_map = new int[m_blocksize];
  }
  /**
   * Construct a IntVector, using the given block size.
   *
   * @param blocksize Size of block to allocate
   */
  public IntVector(int blocksize)
  {
    m_blocksize = blocksize;
    m_mapSize = blocksize;
    m_map = new int[blocksize];
  }
  
  /**
   * Construct a IntVector, using the given block size.
   *
   * @param blocksize Size of block to allocate
   */
  public IntVector(int blocksize, int increaseSize)
  {
    m_blocksize = increaseSize;
    m_mapSize = blocksize;
    m_map = new int[blocksize];
  }
  /**
   * Copy constructor for IntVector
   * 
   * @param v Existing IntVector to copy
   */
  public IntVector(IntVector v)
  {
    m_map = new int[v.m_mapSize];
    m_mapSize = v.m_mapSize;
    m_firstFree = v.m_firstFree;
    m_blocksize = v.m_blocksize;
    System.arraycopy(v.m_map, 0, m_map, 0, m_firstFree);
  }
  /**
   * Get the length of the list.
   *
   * @return length of the list
   */
  public final int size()
  {
    return m_firstFree;
  }
  
  /**
   * Get the length of the list.
   *
   * @return length of the list
   */
  public final void setSize(int sz)
  {
    m_firstFree = sz;
  }

  /**
   * Append a int onto the vector.
   *
   * @param value Int to add to the list 
   */
  public final void addElement(int value)
  {
    if ((m_firstFree + 1) >= m_mapSize)
    {
      m_mapSize += m_blocksize;
      int newMap[] = new int[m_mapSize];
      System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
      m_map = newMap;
    }
    m_map[m_firstFree] = value;
    m_firstFree++;
  }
  
  /**
   * Append several int values onto the vector.
   *
   * @param value Int to add to the list 
   */
  public final void addElements(int value, int numberOfElements)
  {
    if ((m_firstFree + numberOfElements) >= m_mapSize)
    {
      m_mapSize += (m_blocksize+numberOfElements);
      int newMap[] = new int[m_mapSize];
      System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
      m_map = newMap;
    }
    for (int i = 0; i < numberOfElements; i++) 
    {
      m_map[m_firstFree] = value;
      m_firstFree++;
    }
  }
  
  /**
   * Append several slots onto the vector, but do not set the values.
   *
   * @param numberOfElements Int to add to the list 
   */
  public final void addElements(int numberOfElements)
  {
    if ((m_firstFree + numberOfElements) >= m_mapSize)
    {
      m_mapSize += (m_blocksize+numberOfElements);
      int newMap[] = new int[m_mapSize];
      System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
      m_map = newMap;
    }
    
    m_firstFree += numberOfElements;
  }
  
  /**
   * Inserts the specified node in this vector at the specified index.
   * Each component in this vector with an index greater or equal to
   * the specified index is shifted upward to have an index one greater
   * than the value it had previously.
   *
   * @param value Int to insert
   * @param at Index of where to insert 
   */
  public final void insertElementAt(int value, int at)
  {
    if ((m_firstFree + 1) >= m_mapSize)
    {
      m_mapSize += m_blocksize;
      int newMap[] = new int[m_mapSize];
      System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
      m_map = newMap;
    }
    if (at <= (m_firstFree - 1))
    {
      System.arraycopy(m_map, at, m_map, at + 1, m_firstFree - at);
    }
    m_map[at] = value;
    m_firstFree++;
  }
  /**
   * Inserts the specified node in this vector at the specified index.
   * Each component in this vector with an index greater or equal to
   * the specified index is shifted upward to have an index one greater
   * than the value it had previously.
   */
  public final void removeAllElements()
  {
    for (int i = 0; i < m_firstFree; i++)
    {
      m_map[i] = java.lang.Integer.MIN_VALUE;
    }
    m_firstFree = 0;
  }
  /**
   * Removes the first occurrence of the argument from this vector.
   * If the object is found in this vector, each component in the vector
   * with an index greater or equal to the object"s index is shifted
   * downward to have an index one smaller than the value it had
   * previously.
   *
   * @param s Int to remove from array
   *
   * @return True if the int was removed, false if it was not found
   */
  public final boolean removeElement(int s)
  {
    for (int i = 0; i < m_firstFree; i++)
    {
      if (m_map[i] == s)
      {
        if ((i + 1) < m_firstFree)
          System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
        else
          m_map[i] = java.lang.Integer.MIN_VALUE;
        m_firstFree--;
        return true;
      }
    }
    return false;
  }
  /**
   * Deletes the component at the specified index. Each component in
   * this vector with an index greater or equal to the specified
   * index is shifted downward to have an index one smaller than
   * the value it had previously.
   *
   * @param i index of where to remove and int
   */
  public final void removeElementAt(int i)
  {
    if (i > m_firstFree)
      System.arraycopy(m_map, i + 1, m_map, i, m_firstFree);
    else
      m_map[i] = java.lang.Integer.MIN_VALUE;
    m_firstFree--;
  }
  /**
   * Sets the component at the specified index of this vector to be the
   * specified object. The previous component at that position is discarded.
   *
   * The index must be a value greater than or equal to 0 and less
   * than the current size of the vector.
   *
   * @param value object to set
   * @param index Index of where to set the object
   */
  public final void setElementAt(int value, int index)
  {
    m_map[index] = value;
  }
  /**
   * Get the nth element.
   *
   * @param i index of object to get
   *
   * @return object at given index
   */
  public final int elementAt(int i)
  {
    return m_map[i];
  }
  /**
   * Tell if the table contains the given node.
   *
   * @param s object to look for
   *
   * @return true if the object is in the list
   */
  public final boolean contains(int s)
  {
    for (int i = 0; i < m_firstFree; i++)
    {
      if (m_map[i] == s)
        return true;
    }
    return false;
  }
  /**
   * Searches for the first occurence of the given argument,
   * beginning the search at index, and testing for equality
   * using the equals method.
   *
   * @param elem object to look for
   * @param index Index of where to begin search
   * @return the index of the first occurrence of the object
   * argument in this vector at position index or later in the
   * vector; returns -1 if the object is not found.
   */
  public final int indexOf(int elem, int index)
  {
    for (int i = index; i < m_firstFree; i++)
    {
      if (m_map[i] == elem)
        return i;
    }
    return java.lang.Integer.MIN_VALUE;
  }
  /**
   * Searches for the first occurence of the given argument,
   * beginning the search at index, and testing for equality
   * using the equals method.
   *
   * @param elem object to look for
   * @return the index of the first occurrence of the object
   * argument in this vector at position index or later in the
   * vector; returns -1 if the object is not found.
   */
  public final int indexOf(int elem)
  {
    for (int i = 0; i < m_firstFree; i++)
    {
      if (m_map[i] == elem)
        return i;
    }
    return java.lang.Integer.MIN_VALUE;
  }
  /**
   * Searches for the first occurence of the given argument,
   * beginning the search at index, and testing for equality
   * using the equals method.
   *
   * @param elem Object to look for
   * @return the index of the first occurrence of the object
   * argument in this vector at position index or later in the
   * vector; returns -1 if the object is not found.
   */
  public final int lastIndexOf(int elem)
  {
    for (int i = (m_firstFree - 1); i >= 0; i--)
    {
      if (m_map[i] == elem)
        return i;
    }
    return java.lang.Integer.MIN_VALUE;
  }
  
  /**
   * Returns clone of current IntVector
   * 
   * @return clone of current IntVector
   */
  public Object clone()
    throws CloneNotSupportedException
  {
    return new IntVector(this);
  }
  
}





The character array based string

/*
 * 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.
 */
/**
 * 
 * @author Eric Ye, IBM
 * @author Andy Clark, IBM
 * 
 * @version $Id: XMLString.java 447247 2006-09-18 05:23:52Z mrglavas $
 */
public class XMLString {
  /** The character array. */
  public char[] ch;
  /** The offset into the character array. */
  public int offset;
  /** The length of characters from the offset. */
  public int length;
  //
  // Constructors
  //
  /** Default constructor. */
  public XMLString() {
  } // <init>()
  /**
   * Constructs an XMLString structure preset with the specified values.
   * 
   * @param ch
   *          The character array.
   * @param offset
   *          The offset into the character array.
   * @param length
   *          The length of characters from the offset.
   */
  public XMLString(char[] ch, int offset, int length) {
    setValues(ch, offset, length);
  } // <init>(char[],int,int)
  /**
   * Constructs an XMLString structure with copies of the values in the given
   * structure.
   * 
   * <strong>Note:</strong> This does not copy the character array; only the
   * reference to the array is copied.
   * 
   * @param string
   *          The XMLString to copy.
   */
  public XMLString(XMLString string) {
    setValues(string);
  } // <init>(XMLString)
  //
  // Public methods
  //
  /**
   * Initializes the contents of the XMLString structure with the specified
   * values.
   * 
   * @param ch
   *          The character array.
   * @param offset
   *          The offset into the character array.
   * @param length
   *          The length of characters from the offset.
   */
  public void setValues(char[] ch, int offset, int length) {
    this.ch = ch;
    this.offset = offset;
    this.length = length;
  } // setValues(char[],int,int)
  /**
   * Initializes the contents of the XMLString structure with copies of the
   * given string structure.
   * 
   * <strong>Note:</strong> This does not copy the character array; only the
   * reference to the array is copied.
   * 
   * @param s
   */
  public void setValues(XMLString s) {
    setValues(s.ch, s.offset, s.length);
  } // setValues(XMLString)
  /** Resets all of the values to their defaults. */
  public void clear() {
    this.ch = null;
    this.offset = 0;
    this.length = -1;
  } // clear()
  /**
   * Returns true if the contents of this XMLString structure and the specified
   * array are equal.
   * 
   * @param ch
   *          The character array.
   * @param offset
   *          The offset into the character array.
   * @param length
   *          The length of characters from the offset.
   */
  public boolean equals(char[] ch, int offset, int length) {
    if (ch == null) {
      return false;
    }
    if (this.length != length) {
      return false;
    }
    for (int i = 0; i < length; i++) {
      if (this.ch[this.offset + i] != ch[offset + i]) {
        return false;
      }
    }
    return true;
  } // equals(char[],int,int):boolean
  /**
   * Returns true if the contents of this XMLString structure and the specified
   * string are equal.
   * 
   * @param s
   *          The string to compare.
   */
  public boolean equals(String s) {
    if (s == null) {
      return false;
    }
    if (length != s.length()) {
      return false;
    }
    // is this faster than call s.toCharArray first and compare the
    // two arrays directly, which will possibly involve creating a
    // new char array object.
    for (int i = 0; i < length; i++) {
      if (ch[offset + i] != s.charAt(i)) {
        return false;
      }
    }
    return true;
  } // equals(String):boolean
  //
  // Object methods
  //
  /** Returns a string representation of this object. */
  public String toString() {
    return length > 0 ? new String(ch, offset, length) : "";
  } // toString():String
} // class XMLString





Your own auto-growth Array

/*
 * 
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:  
 *       "This product includes software developed by the 
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Jakarta Element Construction Set", 
 *    "Jakarta ECS" , and "Apache Software Foundation" must not be used 
 *    to endorse or promote products derived
 *    from this software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Jakarta Element Construction Set" nor "Jakarta ECS" nor may "Apache" 
 *    appear in their names without prior written permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

public class Array implements java.util.Enumeration,java.io.Serializable
{
    private int current = 0;
    private int size = 10;
    private int grow = 2;
    private int place = 0;
    private Object[] elements = null;
    private Object[] tmpElements = null;
    public Array()
    {
        init();
    }
    public Array(int size)
    {
        setSize(size);
        init();
    }
    public Array(int size,int grow)
    {
        setSize(size);
        setGrow(grow);
        init();
    }
    private void init()
    {
        elements = new Object[size];
    }
    public Object nextElement() throws java.util.NoSuchElementException
    {
        if ( elements[place] != null && place != current)
        {
            place++;
            return elements[place - 1];
        }
        else
        {
            place = 0;
            throw new java.util.NoSuchElementException();
        }
    }
    public boolean hasMoreElements()
    {
        if( place < elements.length && current != place )
            return true;
        return false;
    }
    public void setSize(int size)
    {
        this.size = size;
    }
    public int getCurrentSize()
    {
        return current;
    }
    public void rehash()
    {
        tmpElements = new Object[size];
        int count = 0;
        for ( int x = 0; x < elements.length; x++ )
        {
            if( elements[x] != null )
            {
                tmpElements[count] = elements[x];
                count++;
            }
        }
        elements = (Object[])tmpElements.clone();
        tmpElements = null;
        current = count;
    }
    public void setGrow(int grow)
    {
        this.grow = grow;
    }
    public void grow()
    {
        size = size+=(size/grow);
        rehash();
    }
    public void add(Object o)
    {
        if( current == elements.length )
            grow();
        try
        {
            elements[current] = o;
            current++;
        }
        catch(java.lang.ArrayStoreException ase)
        {
        }
    }
    public void add(int location,Object o)
    {
        try
        {
            elements[location] = o;
        }
        catch(java.lang.ArrayStoreException ase)
        {
        }
    }
    public void remove(int location)
    {
        elements[location] = null;
    }
    public int location(Object o) throws NoSuchObjectException
    {
        int loc = -1;
        for ( int x = 0; x < elements.length; x++ )
        {
            if((elements[x] != null && elements[x] == o )||
               (elements[x] != null && elements[x].equals(o)))
            {
                loc = x;
                break;
            }
        }
        if( loc == -1 )
            throw new NoSuchObjectException();
        return(loc);
    }
    public Object get(int location)
    {
        return elements[location];
    }
    public java.util.Enumeration elements()
    {
        return this;
    }
}
class NoSuchObjectException extends Exception
{
    public NoSuchObjectException()
    {
        super("No such object found.");
    }
}