Java Data Structure How to - Create elements List backed by array








Question

We would like to know how to create elements List backed by array.

Answer

/*//w  ww .  j a va2  s  .c  o m
 * This file is a part of Alchemy OS project.
 *  Copyright (C) 2011-2013, Sergey Basalaev <sbasalaev@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package alchemy.util;

/**
 * List of elements backed by array.
 * <p>
 * Unlike <code>Vector</code> this class is not synchronized.
 *
 * @author Sergey Basalaev
 */
public final class ArrayList {
  
  private Object[] elements;
  private int size;

  /** Creates new empty ArrayList with default capacity. */
  public ArrayList() {
    this(16);
  }

  /** Creates new empty ArrayList with given capacity. */
  public ArrayList(int capacity) {
    elements = new Object[capacity];
    size = 0;
  }

  private void growBy(int count) {
    int minCapacity = elements.length + count;
    int newCapacity = (elements.length * 3) / 2 + 1;
    if (newCapacity < minCapacity) newCapacity = minCapacity;
    Object[] data = new Object[newCapacity];
    System.arraycopy(elements, 0, data, 0, size);
    elements = data;
  }

  /** Returns number of elements in this list. */
  public int size() {
    return size;
  }

  /** Returns true if this list contains no elements. */
  public boolean isEmpty() {
    return size == 0;
  }

  /** Removes all elements from this list. */
  public void clear() {
    for (int i=size-1; i>=0; i--) {
      elements[i] = null;
    }
    size = 0;
  }

  /** Returns element at given index. */
  public Object get(int index) {
    if (index < 0 || index >= size)
      throw new IndexOutOfBoundsException();
    return elements[index];
  }

  /** Returns first element of this list. */
  public Object first() {
    if (size == 0) throw new IndexOutOfBoundsException();
    return elements[0];
  }

  /** Returns last element of this list. */
  public Object last() {
    if (size == 0) throw new IndexOutOfBoundsException();
    return elements[size-1];
  }

  /** Sets new value to the elements of this list. */
  public void set(int index, Object e) {
    if (index < 0 || index >= size)
      throw new IndexOutOfBoundsException();
    elements[index] = e;
  }

  /** Inserts element in given position of the list. */
  public void insert(int index, Object e) {
    if (index < 0 || index > size)
      throw new IndexOutOfBoundsException();
    if (elements.length == size)
      growBy(1);
    if (index < size)
      System.arraycopy(elements, index, elements, index+1, size-index);
    elements[index] = e;
    size++;
  }

  /** Inserts elements from given array. */
  public void insertFrom(int index, Object array, int ofs, int len) {
    if (len < 0) len = Arrays.arrayLength(array);
    if (len == 0) return;
    if (elements.length < size + len)
      growBy(len);
    if (index < size)
      System.arraycopy(elements, index, elements, index+len, size-index);
    Arrays.arrayCopy(array, ofs, elements, index, len);
    size += len;
  }

  /** Adds element to the end of the list. */
  public void add(Object e) {
    if (elements.length == size)
      growBy(1);
    elements[size] = e;
    size++;
  }

  /** Adds elements from given array. */
  public void addFrom(Object array, int ofs, int len) {
    if (len < 0) len = Arrays.arrayLength(array);
    if (len == 0) return;
    if (elements.length < size + len)
      growBy(len);
    Arrays.arrayCopy(array, ofs, elements, size, len);
    size += len;
  }

  /** Removes element from given position of the list. */
  public void remove(int index) {
    if (index < 0) index += size;
    if (index < 0 || index >= size) throw new IndexOutOfBoundsException();
    size--;
    if (index < size)
      System.arraycopy(elements, index+1, elements, index, size-index);
    elements[size] = null;
  }

  /** Finds and removes given element. */
  public boolean remove(Object e) {
    int idx = indexOf(e, 0);
    if (idx >= 0) remove(idx);
    return idx >= 0;
  }

  /** Returns sublist of this list. */
  public ArrayList getRange(int from, int to) {
    if (from < 0) from += size;
    if (to < 0) to += size;
    int len = to-from;
    ArrayList list = new ArrayList(len);
    list.size = len;
    System.arraycopy(elements, from, list.elements, 0, len);
    return list;
  }

  /** Tests whether list contains given element. */
  public boolean contains(Object e) {
    return indexOf(e, 0) >= 0;
  }

  /**
   * Returns index of the first occurence of given object
   * after given index.
   * Returns -1 if the list does not contain it.
   */
  public int indexOf(Object e, int from) {
    for (int index = from; index < size; index++) {
      if (e == null ? elements[index] == null : e.equals(elements[index])) {
        return index;
      }
    }
    return -1;
  }

  /**
   * Returns index of the first occurence of given object.
   * Returns -1 if the list does not contain it.
   */
  public int indexOf(Object e) {
    return indexOf(e, 0);
  }

  /**
   * Returns index of the last occurence of given object.
   * Returns -1 if the list does not contain it.
   */
  public int lastIndexOf(Object e) {
    for (int index = size-1; index >= 0; index--) {
      if (e == null ? elements[index] == null : e.equals(elements[index])) {
        return index;
      }
    }
    return -1;
  }

  /**
   * Copies portion of this list into given array.
   * 
   * @param from    index of the first element to copy
   * @param array   object or promitive array to copy into
   * @param offset  offset in array to place first element
   * @param len     number of elements to copy
   */
  public void copyInto(int from, Object array, int offset, int len) {
    if (len < 0) len = Arrays.arrayLength(array);
    if (len == 0) return;
    if (from < 0 || from >= size || len > size || offset < 0 || offset + len > Arrays.arrayLength(array))
      throw new IndexOutOfBoundsException();
    Arrays.arrayCopy(elements, from, array, offset, len);
  }

  /** Copies contents of this list into given array. */
  public void copyInto(Object array) {
    copyInto(0, array, 0, size);
  }

  void buildString(ArrayList dejaVu, StringBuffer buf) {
    if (dejaVu.indexOf(this, 0) >= 0) {
      buf.append("[...]");
    } else {
      dejaVu.add(this);
      buf.append('[');
      for (int i=0; i<size; i++) {
        if (i != 0) buf.append(", ");
        Strings.buildString(elements[i], dejaVu, buf);
      }
      buf.append(']');
      dejaVu.remove(this);
    }
  }

  /** Returns string representation of this list. */
  public String toString() {
    StringBuffer buf = new StringBuffer();
    buildString(new ArrayList(), buf);
    return buf.toString();
  }
}