package com.artemis.utils; /** * Collection type a bit like ArrayList but does not preserve the order of its * entities, speedwise it is very good, especially suited for games. */ public class Bag<E> implements ImmutableBag<E> { private E[] data; private int size = 0; /** * Constructs an empty Bag with an initial capacity of 64. * */ public Bag() { this(64); } /** * Constructs an empty Bag with the specified initial capacity. * * @param capacity * the initial capacity of Bag */ @SuppressWarnings("unchecked") public Bag(int capacity) { data = (E[])new Object[capacity]; } /** * Removes the element at the specified position in this Bag. does this by * overwriting it was last element then removing last element * * @param index * the index of element to be removed * @return element that was removed from the Bag */ public E remove(int index) { E e = data[index]; // make copy of element to remove so it can be returned data[index] = data[--size]; // overwrite item to remove with last element data[size] = null; // null last element, so gc can do its work return e; } /** * Remove and return the last object in the bag. * * @return the last object in the bag, null if empty. */ public E removeLast() { if(size > 0) { E e = data[--size]; data[size] = null; return e; } return null; } /** * Removes the first occurrence of the specified element from this Bag, if * it is present. If the Bag does not contain the element, it is unchanged. * does this by overwriting it was last element then removing last element * * @param e * element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ public boolean remove(E e) { for (int i = 0; i < size; i++) { E e2 = data[i]; if (e == e2) { data[i] = data[--size]; // overwrite item to remove with last element data[size] = null; // null last element, so gc can do its work return true; } } return false; } /** * Check if bag contains this element. * * @param e * @return */ public boolean contains(E e) { for(int i = 0; size > i; i++) { if(e == data[i]) { return true; } } return false; } /** * Removes from this Bag all of its elements that are contained in the * specified Bag. * * @param bag * Bag containing elements to be removed from this Bag * @return {@code true} if this Bag changed as a result of the call */ public boolean removeAll(ImmutableBag<E> bag) { boolean modified = false; for (int i = 0; i < bag.size(); i++) { E e1 = bag.get(i); for (int j = 0; j < size; j++) { E e2 = data[j]; if (e1 == e2) { remove(j); j--; modified = true; break; } } } return modified; } /** * Returns the element at the specified position in Bag. * * @param index * index of the element to return * @return the element at the specified position in bag */ public E get(int index) { return data[index]; } /** * Returns the number of elements in this bag. * * @return the number of elements in this bag */ public int size() { return size; } /** * Returns the number of elements the bag can hold without growing. * * @return the number of elements the bag can hold without growing. */ public int getCapacity() { return data.length; } /** * Checks if the internal storage supports this index. * * @param index * @return */ public boolean isIndexWithinBounds(int index) { return index < getCapacity(); } /** * Returns true if this list contains no elements. * * @return true if this list contains no elements */ public boolean isEmpty() { return size == 0; } /** * Adds the specified element to the end of this bag. if needed also * increases the capacity of the bag. * * @param e * element to be added to this list */ public void add(E e) { // is size greater than capacity increase capacity if (size == data.length) { grow(); } data[size++] = e; } /** * Set element at specified index in the bag. * * @param index position of element * @param e the element */ public void set(int index, E e) { if(index >= data.length) { grow(index*2); } size = index+1; data[index] = e; } private void grow() { int newCapacity = (data.length * 3) / 2 + 1; grow(newCapacity); } @SuppressWarnings("unchecked") private void grow(int newCapacity) { E[] oldData = data; data = (E[])new Object[newCapacity]; System.arraycopy(oldData, 0, data, 0, oldData.length); } public void ensureCapacity(int index) { if(index >= data.length) { grow(index*2); } } /** * Removes all of the elements from this bag. The bag will be empty after * this call returns. */ public void clear() { // null all elements so gc can clean up for (int i = 0; i < size; i++) { data[i] = null; } size = 0; } /** * Add all items into this bag. * @param added */ public void addAll(ImmutableBag<E> items) { for(int i = 0; items.size() > i; i++) { add(items.get(i)); } } }