001: package uk.org.ponder.arrayutil;
002:
003: import java.lang.reflect.Array;
004:
005: import uk.org.ponder.reflect.ClassGetter;
006: import uk.org.ponder.stringutil.CharWrap;
007:
008: /**
009: * This class supplies a selection of useful methods to operate on Java arrays.
010: * With these methods, arrays can behave very much like Vectors, only with much
011: * greater time and space efficiency where the length is short or modifications
012: * are infrequent.
013: */
014:
015: public class ArrayUtil {
016: // TODO: Does the [L syntax also work for primitive types?
017: private static double[] doubleexemplar = new double[0];
018: public static Class doubleArrayClass = doubleexemplar.getClass();
019: private static int[] intexemplar = new int[0];
020: public static Class intArrayClass = intexemplar.getClass();
021: public static Class stringArrayClass = ClassGetter
022: .forName("[Ljava.lang.String;");
023:
024: /**
025: * Concatenates two arrays of the same reference type to return a larger
026: * array.
027: *
028: * @param array1 The first array to be concatenated.
029: * @param array2 The second array to be concatenated.
030: * @return An array whose length is the sum of the lengths of the input
031: * arrays, and contains the elements of the second array appended to
032: * the elements of the first.
033: */
034: public static final Object[] concat(Object[] array1, Object[] array2) {
035: Class component1 = array1.getClass().getComponentType();
036: Object[] togo = (Object[]) Array.newInstance(component1,
037: array1.length + array2.length);
038: System.arraycopy(array1, 0, togo, 0, array1.length);
039: System.arraycopy(array2, 0, togo, array1.length, array2.length);
040: return togo;
041: }
042:
043: /**
044: * Expands the supplied array by the given factor, to return an array with the
045: * same contents padded by null.
046: *
047: * @param array1 The array to be expanded.
048: * @param scalefactor The factor the size of the array is to be enlarged by -
049: * clearly this must be a number greater than 1.0.
050: * @return An array with the required size, with the contents of the supplied
051: * array copied into its first portion.
052: */
053:
054: public static final Object[] expand(Object[] array1,
055: double scalefactor) {
056: Class component1 = array1.getClass().getComponentType();
057: Object[] togo = (Object[]) Array.newInstance(component1,
058: (int) (array1.length * scalefactor));
059: System.arraycopy(array1, 0, togo, 0, array1.length);
060: return togo;
061: }
062:
063: /**
064: * Expands the supplied array to the specified size, to return an array with
065: * the same contents padded by null.
066: *
067: * @param array1 The array to be expanded.
068: * @param newsize The required size of the array.
069: * @return An array with the required size, with the contents of the supplied
070: * array copied into its first portion.
071: */
072:
073: public static final Object[] expand(Object[] array1, int newsize) {
074: Class component1 = array1.getClass().getComponentType();
075: Object[] togo = (Object[]) Array.newInstance(component1,
076: newsize);
077: System.arraycopy(array1, 0, togo, 0, array1.length);
078: return togo;
079: }
080:
081: /**
082: * Expands the supplied array by the given factor, to return an array with the
083: * same contents padded by null.
084: *
085: * @param array1 The array to be expanded.
086: * @param scalefactor The factor the size of the array is to be enlarged by -
087: * clearly this must be a number greater than 1.0.
088: * @return An array with the required size, with the contents of the supplied
089: * array copied into its first portion.
090: */
091:
092: public static final byte[] expand(byte[] array1, double scalefactor) {
093: byte[] togo = new byte[(int) (array1.length * scalefactor)];
094: System.arraycopy(array1, 0, togo, 0, array1.length);
095: return togo;
096: }
097:
098: /**
099: * Trims the supplied array to the specified size, to return an array with
100: * only the elements from the first portion of the supplied array.
101: *
102: * @param array1 The array to be trimmed.
103: * @param tolength The number of elements to be returned from the beginning of
104: * the array.
105: * @return An array containing only the first <code>tolength</code> elements
106: * of the supplied array.
107: */
108:
109: public static final Object[] trim(Object[] array1, int tolength) {
110: Class component1 = array1.getClass().getComponentType();
111: Object[] togo = (Object[]) Array.newInstance(component1,
112: tolength);
113: System.arraycopy(array1, 0, togo, 0, tolength);
114: return togo;
115: }
116:
117: /**
118: * Returns a sub-array whose elements are copied from a range of the entries
119: * in the supplied array.
120: *
121: * @param array1 The source array
122: * @param tolength The number of elements to be returned from the beginning of
123: * the array.
124: * @return An array containing the elements from index <code>start</code>
125: * (inclusive) to index <code>end</code> (not inclusive) from the
126: * source array.
127: */
128:
129: public static final Object[] subArray(Object[] array1, int start,
130: int end) {
131: Class component1 = array1.getClass().getComponentType();
132: Object[] togo = (Object[]) Array.newInstance(component1, end
133: - start);
134: System.arraycopy(array1, start, togo, 0, end - start);
135: return togo;
136: }
137:
138: /**
139: * Appends a single object to the end of the supplied array, returning an
140: * array one element longer than the supplied array.
141: *
142: * @param array1 The array to which the element is to be appended, or
143: * <code>null</code> if no array yet exists.
144: * @param toappend The object to be appended to the array.
145: * @return A new array one element longer than the supplied array, with the
146: * supplied object copied into the final place.
147: */
148:
149: public static final Object[] append(Object[] array1, Object toappend) {
150: Class component1 = array1 == null ? toappend.getClass()
151: : array1.getClass().getComponentType();
152: int length = array1 == null ? 0 : array1.length;
153: Object[] togo = (Object[]) Array.newInstance(component1,
154: length + 1);
155: if (length > 0) {
156: System.arraycopy(array1, 0, togo, 0, array1.length);
157: }
158: togo[length] = toappend;
159: return togo;
160: }
161:
162: /**
163: * Determines whether the supplied array contains a given element. Equality
164: * will be determined by the <code>.equals()</code> method.
165: *
166: * @param array The array to be searched for the supplied element.
167: * @param tofind The element to be found in the array.
168: * @return <code>true</code> if the element was found in the array.
169: */
170:
171: public static final boolean contains(Object[] array, Object tofind) {
172: for (int i = 0; i < array.length; ++i) {
173: if (array[i].equals(tofind))
174: return true;
175: }
176: return false;
177: }
178:
179: /**
180: * Finds the first index that the supplied element appears at in a given
181: * array. Equality will be determined by the <code>.equals()</code> method.
182: *
183: * @param array The array to be searched for the supplied element.
184: * @param tofind The object to be searched for.
185: * @return The first index that the object appears at in the array, or
186: * <code>-1</code> if it is not found.
187: */
188:
189: public static final int indexOf(Object[] array, Object tofind) {
190: for (int i = 0; i < array.length; ++i) {
191: if (array[i].equals(tofind))
192: return i;
193: }
194: return -1;
195: }
196:
197: /**
198: * Finds the first index that the supplied element appears at in a given
199: * array. Equality will be determined by the <code>.equals()</code> method.
200: *
201: * @param array The array to be searched for the supplied element.
202: * @param tofind The object to be searched for.
203: * @return The first index that the object appears at in the array, or
204: * <code>-1</code> if it is not found.
205: */
206:
207: public static final int indexOf(int[] array, int tofind) {
208: for (int i = 0; i < array.length; ++i) {
209: if (array[i] == tofind)
210: return i;
211: }
212: return -1;
213: }
214:
215: /**
216: * Removes an element from an array, by causing all the elements beyond it to
217: * shuffle back one place.
218: *
219: * @param array The array from which the element is to be removed.
220: * @param index The index from which the element is to be removed.
221: * @return The same array that was input, with the elements past the specified
222: * index shuffled back one place.
223: */
224:
225: public static final void removeElementAtShift(Object[] array,
226: int index) {
227: System.arraycopy(array, index + 1, array, index, array.length
228: - index - 1);
229: }
230:
231: public static final Object[] removeElementAt(Object[] array,
232: int index) {
233: Class component1 = array.getClass().getComponentType();
234: Object[] togo = (Object[]) Array.newInstance(component1,
235: array.length - 1);
236:
237: for (int i = 0; i < index; ++i) {
238: togo[i] = array[i];
239: }
240: for (int i = index + 1; i < array.length; ++i) {
241: togo[i - 1] = array[i];
242: }
243:
244: return togo;
245: }
246:
247: public static int lexicalCompare(Comparable[] array1, int length1,
248: Comparable[] array2, int length2) {
249: int i = 0;
250: while (true) {
251: if (i >= length1) {
252: // off the end of 1 means that 1 is possibly shorter
253: if (length1 == length2)
254: return 0;
255: else
256: return -1;
257: }
258: if (i >= length2)
259: return 1;
260: Comparable a1 = array1[i];
261: Comparable a2 = array2[i];
262: if (a1 == null && a2 != null)
263: return -1;
264: if (a2 != null && a2 == null)
265: return 1;
266: if (a1 != null && a2 != null) {
267: if (a1.compareTo(a2) < 0)
268: return -1;
269: else if (a1.compareTo(a2) > 0)
270: return 1;
271: }
272: ++i;
273: }
274: }
275:
276: public static boolean equals(String string, char[] buffer,
277: int start, int length) {
278: if (length != string.length())
279: return false;
280: for (int i = length - 1; i >= 0; --i) {
281: if (buffer[start + i] != string.charAt(i))
282: return false;
283: }
284: return true;
285: }
286:
287: /**
288: * Converts the supplied array into a String for debugging purposes.
289: *
290: * @return A String formed from the results of the <code>.toString()</code>
291: * method on each array element, separated by single space characters.
292: * If the supplied array is null, returns the string <code>null</code>.
293: */
294:
295: public static final String toString(Object[] array) {
296: if (array == null)
297: return "null";
298: CharWrap togo = new CharWrap();
299: for (int i = 0; i < array.length; ++i) {
300: togo
301: .append(array[i] == null ? "null" : array[i]
302: .toString());
303: if (i != array.length - 1)
304: togo.append(' ');
305: }
306: return togo.toString();
307: }
308:
309: }
|