Mega Code Archive

 
Categories / Java / Collections Data Structure
 

Call it an unordered list or a multiset, this collection is defined by oxymorons

//package com.ryanm.util; import java.util.NoSuchElementException; /**  * Call it an unordered list or a multiset, this collection is defined by  * oxymorons. Find the original <a href=http://riven8192.blogspot.com/  * 2009/08/bag-unordered-list-fast-remove.html>over here</a>  *   * @author Riven  * @param <T>  */ public class Bag<T> {   private T[] data;   private int size;   /***/   public Bag() {     this(4);   }   /**    * @param space    *            initial size of bag    */   @SuppressWarnings("unchecked")   public Bag(int space) {     this.data = (T[]) new Object[space];   }   /**    * Add an element    *     * @param t    */   public void put(T t) {     data = ensure(data, size + 1, 1.75f);     data[size++] = t;   }   /**    * Adds a lot of elements    *     * @param bag    */   public void putAll(Bag<T> bag) {     if (bag.size == 0) {       return;     }     data = ensure(data, this.size + bag.size, 1.75f);     System.arraycopy(bag.data, 0, this.data, this.size, bag.size);     this.size += bag.size;   }   /**    * Retrieves an element    *     * @param index    * @return the indexed element    */   public T get(int index) {     if (index >= size) {       throw new ArrayIndexOutOfBoundsException();     }     return data[index];   }   /**    * Retrieves and removes an element    *     * @param index    * @return The indexed element    */   public T take(int index) {     if (index >= size) {       throw new ArrayIndexOutOfBoundsException();     }     T took = data[index];     data[index] = data[--size];     data[size] = null;     return took;   }   /**    * Attempts to remove an element    *     * @param t    *            The element to remove    * @return t    * @throws NoSuchElementException    *             if the element was not found    */   public T take(T t) {     int i = this.indexOf(t);     if (i == -1) {       throw new NoSuchElementException();     }     return this.take(i);   }   /**    * Tests if an element is present    *     * @param t    * @return <code>true</code> if t is present, <code>false</code> otherwise    */   public boolean contains(T t) {     return this.indexOf(t) != -1;   }   /**    * Finds the index of an element    *     * @param t    * @return the index of t, or -1 if not found    */   public int indexOf(T t) {     for (int i = 0; i < size; i++) {       if (data[i] == t) {         return i;       }     }     return -1;   }   /**    * Tries to shrink the internal array. If your {@link Bag} holds a lot of    * elements temporarily and you're concerned with memory usage, it might be    * worthwhile to call this after a sequence of {@link #take(int)} calls    */   @SuppressWarnings("unchecked")   public void shrink() {     if (this.data.length > 8) {       int factor = 4;       if (this.size < this.data.length / factor) {         int newSize = Math.max(4, this.size);         T[] newData = (T[]) new Object[newSize];         System.arraycopy(this.data, 0, newData, 0, this.size);         this.data = newData;       }     }   }   /**    * Removes all elements    */   public void clear() {     for (int i = 0; i < size; i++) {       data[i] = null;     }     this.size = 0;   }   /**    * The maximum number of elements allowed before the internal array will be    * grown    *     * @return The size of the internal array    */   public int capacity() {     return this.data.length;   }   /**    * @return The number of held elements    */   public int size() {     return size;   }   @SuppressWarnings("unchecked")   private static final <T> T[] ensure(T[] src, int minCapacity, float factor) {     if (src.length >= minCapacity) {       return src;     }     int newCapacity = src.length + 1;     do {       newCapacity *= factor;     } while (newCapacity < minCapacity);     T[] dst = (T[]) new Object[newCapacity];     System.arraycopy(src, 0, dst, 0, src.length);     return dst;   } }