1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.utils.datastructures;
\r
14 import java.io.PrintStream;
\r
15 import java.lang.reflect.Array;
\r
16 import java.util.Arrays;
\r
17 import java.util.Collections;
\r
18 import java.util.Iterator;
\r
19 import java.util.NoSuchElementException;
\r
22 * Multi-dimension array utils.
\r
24 * @See {@link Array} related
\r
25 * @See {@link Arrays} related
\r
26 * @See {@link Collections} related
\r
27 * @author Toni Kalajainen (toni.kalajainen@vtt.fi)
\r
29 public class MultiDimensionArrayUtils {
\r
33 * Print multi-dimension array
\r
36 public static void printArrayDeep(Object v, PrintStream out)
\r
38 ArrayIterator<Boolean> i = arrayIterator(v, getArrayLengths(v));
\r
40 System.out.println(Arrays.toString(i.getIndices())+" = "+i.next());
\r
44 * Get array length of each dimension of a multi-dimension array.
\r
46 * @param value multi-dimension array
\r
47 * @return lengths of each dimension
\r
49 public static int[] getArrayLengths(Object value)
\r
51 int dim = getDimension(value.getClass());
\r
52 int result[] = new int[ dim ];
\r
53 if (dim==0) return result;
\r
56 for (int i=0; i<dim; i++)
\r
58 result[i] = Array.getLength(o);
\r
59 if (result[i]==0) break;
\r
60 o = Array.get(o, 0);
\r
67 * Get the number of dimensions in a multi-dimension array.
\r
69 * @param value multi-dimension array
\r
70 * @return the number of dimensions
\r
72 public static int getDimension(Class<?> clazz)
\r
74 String signature = clazz.getName();
\r
76 for (; dim<signature.length(); dim++)
\r
77 if (signature.charAt(dim)!='[') break;
\r
83 * Deep create multi-level array
\r
85 * @param componentType component type
\r
86 * @param dims dimension lengths
\r
87 * @return multi-level array
\r
89 public static Object[] createMultiDimArray(Class<?> componentType, int[] dims)
\r
92 return (Object[]) Array.newInstance(componentType, dims);
\r
96 if (dims==null || componentType==null || dims.length==0) throw new IllegalArgumentException();
\r
97 if (dims.length==1)
\r
98 return Array.newInstance(componentType, dims[0]);
\r
100 int[][] dimArrays = new int[dims.length][];
\r
101 dimArrays[0] = dims;
\r
102 for (int j=1; j<dims.length; j++)
\r
104 dimArrays[j] = new int[dims.length-j];
\r
105 System.arraycopy(dims, 1, dimArrays[j], 0, dims.length-j);
\r
107 return _createMultiDimArray(componentType, dimArrays, 0);
\r
111 private static Object[] _createMultiDimArray(Class<?> componentType, int[][] dimArrays, int lvl)
\r
113 int[] dims = dimArrays[lvl];
\r
115 Object[] result = (Object[]) Array.newInstance(componentType, dims);
\r
116 if (lvl<dimArrays.length-1)
\r
117 for (int i=0; i<len; i++)
\r
118 result[i] = _createMultiDimArray(componentType, dimArrays, lvl+1);
\r
124 * Returns the total number of elements in a multi-dimension array
\r
126 * @param dims lengths of each dimension
\r
127 * @return total number of elements
\r
129 public static int getLength(int[] dims)
\r
132 for (int i=1; i<dims.length; i++)
\r
138 * Get the component type of an array class
\r
140 * @param clazz (array) class
\r
141 * @return component type
\r
143 public static Class<?> getComponentType(Class<?> clazz)
\r
145 Class<?> result = clazz;
\r
146 while (result.isArray())
\r
147 result = result.getComponentType();
\r
152 * Demux single-dimension array (x[]) to a multi-dimension array (x[][][])
\r
154 * @param src single-dimension array
\r
156 * @return multi-dimension array
\r
158 public static Object demuxArray(Object src, int[] dims)
\r
160 return demuxArray(src, dims, getComponentType(src.getClass()));
\r
164 * Demux single-dimension array (x[]) to a multi-dimension array (x[][][])
\r
166 * @param src single-dimension array
\r
168 * @param componentType
\r
169 * @return multi-dimension array
\r
171 public static Object demuxArray(Object src, int[] dims, Class<?> componentType)
\r
173 Object dst = Array.newInstance(componentType, dims);
\r
174 _fillDemux(0, dims, src, 0, dst);
\r
179 * Demuxes single dimension array into a multi-dimension array
\r
181 * @param src one dimension array (e.g. int[])
\r
182 * @param dimensions length of each dimension
\r
183 * @param dst multi-dimension array to be filled (use createMultiDimArray())
\r
185 public static void demuxArray(Object src, int[] dims, Object dst)
\r
187 if (Array.getLength(src) != getLength(dims))
\r
188 throw new IllegalArgumentException("The length of src does not match the length of dst");
\r
189 _fillDemux(0, dims, src, 0, dst);
\r
192 private static int _fillDemux(int lvl, int[] dims, Object src, int srcIndex, Object dst)
\r
195 if (lvl==dims.length-1) {
\r
196 int len = dims[dims.length-1];
\r
197 System.arraycopy(src, srcIndex, dst, 0, len);
\r
198 return srcIndex + len;
\r
201 for (int i=0; i<dims[lvl]; i++)
\r
202 srcIndex = _fillDemux(lvl+1, dims, src, srcIndex, Array.get(dst, i));
\r
208 * Multiplex multi-dimension array (x[][][]) to single-dimension array (x[])
\r
210 * @param src multi-dimension array
\r
211 * @return single-dimension array
\r
213 public static Object muxArray(Object src)
\r
215 return muxArray(src, getArrayLengths(src), getComponentType(src.getClass()));
\r
219 * Multiplex multi-dimension array (x[][][]) to single-dimension array (x[])
\r
221 * @param src multi-dimension array
\r
223 * @return single-dimension array
\r
225 public static Object muxArray(Object src, int[] dims)
\r
227 return muxArray(src, dims, getComponentType(src.getClass()));
\r
231 * Multiplex multi-dimension array (x[][][]) to single-dimension array (x[])
\r
233 * @param src multi-dimension array
\r
235 * @param componentType
\r
236 * @return single-dimension array
\r
238 public static Object muxArray(Object src, int[] dims, Class<?> componentType)
\r
240 int len = getLength(dims);
\r
241 Object dst = Array.newInstance(componentType, len);
\r
242 muxArray(src, dims, dst);
\r
247 * Multiplexes multi-dimension array into a single-dimension array
\r
249 * @param src multi-dimension array
\r
250 * @param dims dimensions
\r
251 * @param dst single-dimension array
\r
253 public static void muxArray(Object src, int[] dims, Object dst)
\r
255 int len = getLength(dims);
\r
256 if (Array.getLength(dst) != len)
\r
257 throw new IllegalArgumentException("The length of src does not match the length of dst");
\r
259 _fillMux(0, dims, src, dst, 0);
\r
262 private static int _fillMux(int lvl, int[] dims, Object src, Object dst, int dstIndex)
\r
264 if (lvl == dims.length-1)
\r
266 int len = dims[lvl];
\r
267 System.arraycopy(src, 0, dst, dstIndex, len);
\r
268 return dstIndex + len;
\r
271 for (int i=0; i<dims[lvl]; i++)
\r
272 dstIndex += _fillMux(lvl+1, dims, Array.get(src, i), dst, dstIndex);
\r
277 public static <R> ArrayIterator<R> arrayIterator(Object array, int[] dimLens)
\r
279 return new ArrayIterator<R>(array, dimLens);
\r
282 public static class ArrayIterator<T> implements Iterator<T>
\r
288 int lastIndex, len;
\r
289 boolean hasNext = true;
\r
291 ArrayIterator(Object array, int[] dimLens)
\r
294 this.dims = dimLens;
\r
295 this.indices = new int[dimLens.length];
\r
296 this.arrays = new Object[dimLens.length];
\r
297 lastIndex = dimLens.length-1;
\r
298 @SuppressWarnings("unused")
\r
299 int len = dimLens[0];
\r
300 for (int i=0; i<=lastIndex; i++)
\r
301 if (dimLens[i]==0) hasNext = false;
\r
302 for (int i=1; i<=lastIndex; i++)
\r
304 arrays[0] = (Object[]) v;
\r
305 for (int i=1; i<dimLens.length; i++)
\r
306 arrays[i] = ((Object[])arrays[i-1])[0];
\r
309 public int[] getIndices()
\r
315 public boolean hasNext() {
\r
319 private void _next() {
\r
320 int index = lastIndex;
\r
321 while (++indices[index] >= dims[index])
\r
323 indices[index] = 0;
\r
329 arrays[index+1] = ((Object[]) arrays[index])[indices[index]];
\r
331 if (index<lastIndex)
\r
332 for (int i=index+1; i<=lastIndex; i++)
\r
333 arrays[i] = ((Object[])arrays[i-1])[indices[i-1]];
\r
336 @SuppressWarnings("unchecked")
\r
340 throw new NoSuchElementException();
\r
342 T result = (T) Array.get(Array.get(arrays, lastIndex), indices[lastIndex]);
\r
348 public void remove() {
\r
349 throw new UnsupportedOperationException("Cannot remove array element");
\r