User:Chase-san/VDA
Jump to navigation
Jump to search
A variable dimension array I wrote up trying to figure out a way I could have a variable number of segment buffers without having to know how many I had in advance. It turned out pretty well!
package org.csdgn.utils; import java.io.Serializable; import java.util.Arrays; /** * Variable Dimension Array, an array class with flexible dimensionality. * * Just remember (int ... x) means it accepts (0,0,0) and new int[]{0,0,0}. * * @author Chase * * @param <T> Type of data contained */ public class VDA<T> implements Serializable, Cloneable { private static final long serialVersionUID = 3816532930303382063L; private T[] data = null; private int[] dims = null; private boolean constructed = false; /** * Initializes the VDA with 0 dimensions. */ public VDA() { dims = new int[0]; } /** * Initializes the VDA with the given number of dimensions * @param dimensions */ public VDA(int ... dimensions) { if(dimensions == null) throw new NullPointerException(); dims = (int[])dimensions.clone(); } /** * @param size Must be at least 2 */ public void add(int size) { if(size < 2) throw new IllegalArgumentException("Dimension size must be at least 2."); dims = Arrays.copyOf(dims, dims.length+1); dims[dims.length-1] = size; constructed = false; } /** * @param index Must be between 0 and number of dimensions */ public void remove(int index) { if(index < 0 || index >= dims.length) throw new IndexOutOfBoundsException(); int[] tmp = dims; dims = Arrays.copyOf(dims, dims.length-1); if(index < dims.length) { System.arraycopy(tmp, index+1, dims, index, dims.length - index); } constructed = false; } /** * Get the value at the given dimension */ public T get(int ... pos) { if(pos == null) throw new NullPointerException(); if(dims.length == 0 || pos.length != dims.length) throw new IllegalArgumentException("Incorrect or Bad Dimensionality."); if(!constructed) construct(); return data[getIndex(pos)]; } /** * Set the value at the given dimension */ public void set(T value, int ... pos) { if(pos == null) throw new NullPointerException(); if(dims.length == 0 || pos.length != dims.length) throw new IllegalArgumentException("Incorrect or Bad Dimensionality."); if(!constructed) construct(); data[getIndex(pos)] = value; } /** * Returns the bottom array at the given position */ public T[] getSubArray(int ... pos) { if(pos.length != dims.length - 1) throw new UnsupportedOperationException( "Dimensionality must be one less than the total supported."); if(!constructed) construct(); int start = getIndex(pos); int length = dims[dims.length-1]; T[] output = createArray(length); System.arraycopy(data, start, output, 0, length); return output; } /** * Sets the bottom array at the given position */ public void setSubArray(T[] array, int ... pos) { if(pos.length != dims.length - 1) throw new UnsupportedOperationException( "Dimensionality must be one less than the total supported."); if(!constructed) construct(); int start = getIndex(pos); int length = Math.min(dims[dims.length-1], array.length); System.arraycopy(array, 0, data, start, length); } /** * @return the array that backs this VDA */ public Object[] getBackingArray() { if(!constructed) construct(); return data; } /** * Returns an array containing all of the elements in this VDA */ public Object[] toArray() { if(!constructed) construct(); return data.clone(); } /** * Returns an array containing all of the elements in this VDA */ @SuppressWarnings("unchecked") public T[] toArray(T[] a) { if(!constructed) construct(); return (T[])Arrays.copyOf(data, data.length, a.getClass()); } /** * Sets this VDA to be equal to the given VDA. Data and dimensions are copied. */ public void set(VDA<T> vda) { data = (T[])vda.data.clone(); dims = (int[])vda.dims.clone(); constructed = vda.constructed; } /** * Returns a shallow copy of this VDA (dimensions but not data) */ public Object clone() { return new VDA<T>(dims); } /** * Creates the final data array */ private void construct() { Integer size = 1; for(Integer i : dims) size *= i; data = createArray(size); constructed = true; } @SuppressWarnings("unchecked") private T[] createArray(int size) { //Warning: Dangerous return (T[])new Object[size]; } /** * Gets the main arrays index from pos */ private int getIndex(int[] pos) { Integer index = 0; for(int i=0; i<pos.length; ++i) { if(pos[i] < 0 || pos[i] >= dims[i]) throw new IndexOutOfBoundsException( "Index " + pos[i] + " is out of bounds for dimension " + i + "."); index += sizeUnder(i)*pos[i]; } System.out.println("Index " + index); return index; } /** * Gets the number of elements under the given level */ private int sizeUnder(int level) { Integer size = 1; for(int i=level+1; i<dims.length; ++i) { size *= dims[i]; } return size; } }