001 package com.croftsoft.core.util;
002
003 import java.lang.reflect.Array;
004 import java.util.Enumeration;
005 import java.util.Hashtable;
006
007 import com.croftsoft.core.lang.NullArgumentException;
008 import com.croftsoft.core.lang.ObjectLib;
009
010 /*********************************************************************
011 * Array manipulation for Java 1.1+.
012 *
013 * <p>
014 * Java 1.1 compatible.
015 * </p>
016 *
017 * @see
018 * ArrayLib2
019 *
020 * @version
021 * 2003-04-07
022 * @since
023 * 2001-04-06
024 * @author
025 * <a href="http://croftsoft.com/">David Wallace Croft</a>
026 *********************************************************************/
027
028 public final class ArrayLib
029 //////////////////////////////////////////////////////////////////////
030 //////////////////////////////////////////////////////////////////////
031 {
032
033 public static void main ( String [ ] args )
034 //////////////////////////////////////////////////////////////////////
035 {
036 System.out.println ( test ( args ) );
037 }
038
039 public static boolean test ( String [ ] args )
040 //////////////////////////////////////////////////////////////////////
041 {
042 try
043 {
044 insert ( new int [ ] { }, 0, 0 );
045
046 String [ ] stringArray
047 = ( String [ ] ) append ( new String [ ] { }, "" );
048
049 stringArray
050 = ( String [ ] ) insert ( new String [ ] { }, "", 0 );
051
052 stringArray
053 = ( String [ ] ) remove ( new String [ ] { "" }, 0 );
054
055 return true;
056 }
057 catch ( Exception ex )
058 {
059 ex.printStackTrace ( );
060
061 return false;
062 }
063 }
064
065 //////////////////////////////////////////////////////////////////////
066 //////////////////////////////////////////////////////////////////////
067
068 /*********************************************************************
069 * Appends an Object to an Object array.
070 *
071 * <p>
072 * Example:
073 * <code>
074 * <pre>
075 * String [ ] stringArray
076 * = ( String [ ] ) ArrayLib.append ( new String [ ] { }, "" );
077 * </pre>
078 * </code>
079 * </p>
080 *
081 * @throws NullArgumentException
082 *
083 * If either argument is null.
084 *
085 * @return
086 *
087 * Returns a new array with the same component type as the old array.
088 *********************************************************************/
089 public static Object [ ] append ( Object [ ] oldArray, Object o )
090 //////////////////////////////////////////////////////////////////////
091 {
092 NullArgumentException.check ( oldArray );
093
094 NullArgumentException.check ( o );
095
096 Object [ ] newArray = ( Object [ ] ) Array.newInstance (
097 oldArray.getClass ( ).getComponentType ( ), oldArray.length + 1 );
098
099 System.arraycopy ( oldArray, 0, newArray, 0, oldArray.length );
100
101 newArray [ oldArray.length ] = o;
102
103 return newArray;
104 }
105
106 /*********************************************************************
107 * Appends an integer to an integer array.
108 *
109 * @param intArray
110 *
111 * May be null.
112 *********************************************************************/
113 public static int [ ] append ( int [ ] intArray, int i )
114 //////////////////////////////////////////////////////////////////////
115 {
116 if ( intArray == null )
117 {
118 return new int [ ] { i };
119 }
120
121 int intArrayLength = intArray.length;
122
123 int [ ] newIntArray = new int [ intArrayLength + 1 ];
124
125 System.arraycopy ( intArray, 0, newIntArray, 0, intArrayLength );
126
127 newIntArray [ intArrayLength ] = i;
128
129 return newIntArray;
130 }
131
132 /*********************************************************************
133 * Determines if an array contains an equivalent object.
134 *
135 * @param objectArray
136 *
137 * May not be null.
138 *
139 * @param o
140 *
141 * If null, function will return true if an array element is null.
142 *********************************************************************/
143 public static boolean contains (
144 Object [ ] objectArray,
145 Object o )
146 //////////////////////////////////////////////////////////////////////
147 {
148 NullArgumentException.check ( objectArray );
149
150 for ( int i = 0; i < objectArray.length; i++ )
151 {
152 if ( ObjectLib.equivalent ( objectArray [ i ], o ) )
153 {
154 return true;
155 }
156 }
157
158 return false;
159 }
160
161 /*********************************************************************
162 * Compares two object arrays for equivalency.
163 *
164 * <p>
165 * A Java 1.1 version of the Java 1.2 method java.util.Arrays.equals().
166 * </p>
167 *********************************************************************/
168 public static boolean equals (
169 Object [ ] objectArray1,
170 Object [ ] objectArray2 )
171 //////////////////////////////////////////////////////////////////////
172 {
173 if ( objectArray1 == null )
174 {
175 return objectArray2 == null;
176 }
177 else if ( objectArray2 == null )
178 {
179 return false;
180 }
181
182 if ( objectArray1.length != objectArray2.length )
183 {
184 return false;
185 }
186
187 for ( int i = 0; i < objectArray1.length; i++ )
188 {
189 Object element1 = objectArray1 [ i ];
190
191 Object element2 = objectArray2 [ i ];
192
193 if ( element1 == null )
194 {
195 if ( element2 != null )
196 {
197 return false;
198 }
199 }
200 else if ( !element1.equals ( element2 ) )
201 {
202 return false;
203 }
204 }
205
206 return true;
207 }
208
209 /*********************************************************************
210 * Inserts an integer into an integer array at the index position.
211 *********************************************************************/
212 public static int [ ] insert (
213 int [ ] intArray,
214 int i,
215 int index )
216 //////////////////////////////////////////////////////////////////////
217 {
218 NullArgumentException.check ( intArray );
219
220 if ( ( index < 0 )
221 || ( index > intArray.length ) )
222 {
223 throw new IllegalArgumentException (
224 "index out of range: " + index );
225 }
226
227 int intArrayLength = intArray.length;
228
229 int [ ] newIntArray = new int [ intArrayLength + 1 ];
230
231 System.arraycopy ( intArray, 0, newIntArray, 0, index );
232
233 newIntArray [ index ] = i;
234
235 System.arraycopy (
236 intArray, index, newIntArray, index + 1, intArrayLength - index );
237
238 return newIntArray;
239 }
240
241 /*********************************************************************
242 * Inserts an Object into an Object array at the index position.
243 *
244 * <p>
245 * Example:
246 * <code>
247 * <pre>
248 * String [ ] stringArray
249 * = ( String [ ] ) ArrayLib.insert ( new String [ ] { }, "", 0 );
250 * </pre>
251 * </code>
252 * </p>
253 *
254 * @throws NullArgumentException
255 *
256 * If objectArray or o is null.
257 *
258 * @throws IndexOutOfBoundsException
259 *
260 * If index < 0 or index > objectArray.length.
261 *
262 * @return
263 *
264 * Returns a new array with the same component type as the old array.
265 *********************************************************************/
266 public static Object [ ] insert (
267 Object [ ] objectArray,
268 Object o,
269 int index )
270 //////////////////////////////////////////////////////////////////////
271 {
272 NullArgumentException.check ( objectArray );
273
274 NullArgumentException.check ( o );
275
276 if ( ( index < 0 )
277 || ( index > objectArray.length ) )
278 {
279 throw new IndexOutOfBoundsException (
280 "index out of range: " + index );
281 }
282
283 Object [ ] newObjectArray = ( Object [ ] ) Array.newInstance (
284 objectArray.getClass ( ).getComponentType ( ),
285 objectArray.length + 1 );
286
287
288 System.arraycopy ( objectArray, 0, newObjectArray, 0, index );
289
290 newObjectArray [ index ] = o;
291
292 System.arraycopy ( objectArray, index, newObjectArray, index + 1,
293 objectArray.length - index );
294
295 return newObjectArray;
296 }
297
298 /*********************************************************************
299 * Prepends an Object to an Object array.
300 *
301 * <p>
302 * Example:
303 * <code>
304 * <pre>
305 * String [ ] stringArray
306 * = ( String [ ] ) ArrayLib.prepend ( new String [ ] { }, "" );
307 * </pre>
308 * </code>
309 * </p>
310 *
311 * @throws NullArgumentException
312 *
313 * If either argument is null.
314 *
315 * @return
316 *
317 * Returns a new array with the same component type as the old array.
318 *********************************************************************/
319 public static Object [ ] prepend ( Object [ ] oldArray, Object o )
320 //////////////////////////////////////////////////////////////////////
321 {
322 NullArgumentException.check ( oldArray );
323
324 NullArgumentException.check ( o );
325
326 Object [ ] newArray = ( Object [ ] ) Array.newInstance (
327 oldArray.getClass ( ).getComponentType ( ), oldArray.length + 1 );
328
329 System.arraycopy ( oldArray, 0, newArray, 1, oldArray.length );
330
331 newArray [ 0 ] = o;
332
333 return newArray;
334 }
335
336 /*********************************************************************
337 * Prints each array element to the standard output.
338 *********************************************************************/
339 public static void println ( Object [ ] objectArray )
340 //////////////////////////////////////////////////////////////////////
341 {
342 for ( int i = 0; i < objectArray.length; i++ )
343 {
344 System.out.println ( objectArray [ i ] );
345 }
346 }
347
348 /*********************************************************************
349 * Removes an Object from an Object array.
350 *
351 * <p>
352 * Example:
353 * <code>
354 * <pre>
355 * String [ ] stringArray
356 * = ( String [ ] ) remove ( new String [ ] { "" }, 0 );
357 * </pre>
358 * </code>
359 * </p>
360 *
361 * @throws NullArgumentException
362 *
363 * If oldArray is null.
364 *
365 * @throws ArrayIndexOutOfBoundsException
366 *
367 * If index < 0 or index >= oldArray.length.
368 *
369 * @return
370 *
371 * Returns a new array with the same component type as the old array.
372 *********************************************************************/
373 public static Object [ ] remove ( Object [ ] oldArray, int index )
374 //////////////////////////////////////////////////////////////////////
375 {
376 NullArgumentException.check ( oldArray );
377
378 if ( ( index < 0 )
379 || ( index >= oldArray.length ) )
380 {
381 throw new ArrayIndexOutOfBoundsException ( index );
382 }
383
384 Object [ ] newArray = ( Object [ ] ) Array.newInstance (
385 oldArray.getClass ( ).getComponentType ( ), oldArray.length - 1 );
386
387 System.arraycopy ( oldArray, 0, newArray, 0, index );
388
389 System.arraycopy (
390 oldArray, index + 1, newArray, index, newArray.length - index );
391
392 return newArray;
393 }
394
395 public static Object [ ] remove ( Object [ ] oldArray, Object o )
396 //////////////////////////////////////////////////////////////////////
397 {
398 NullArgumentException.check ( oldArray );
399
400 int index = -1;
401
402 for ( int i = 0; i < oldArray.length; i++ )
403 {
404 if ( oldArray [ i ] == o )
405 {
406 index = i;
407
408 break;
409 }
410 }
411
412 if ( index > -1 )
413 {
414 return remove ( oldArray, index );
415 }
416
417 return oldArray;
418 }
419
420 /*********************************************************************
421 * Removes duplicate elements from the array.
422 *********************************************************************/
423 public static Object [ ] removeDuplicates ( Object [ ] array )
424 //////////////////////////////////////////////////////////////////////
425 {
426 NullArgumentException.check ( array );
427
428 Hashtable hashtable = new Hashtable ( );
429
430 for ( int i = 0; i < array.length; i++ )
431 {
432 hashtable.put ( array [ i ], array [ i ] );
433 }
434
435 Object [ ] newArray = ( Object [ ] ) Array.newInstance (
436 array.getClass ( ).getComponentType ( ), hashtable.size ( ) );
437
438 int index = 0;
439
440 Enumeration enumeration = hashtable.elements ( );
441
442 while ( enumeration.hasMoreElements ( ) )
443 {
444 newArray [ index++ ] = enumeration.nextElement ( );
445 }
446
447 return newArray;
448 }
449
450 /*********************************************************************
451 * Creates a new subarray from a larger array.
452 *
453 * <p>
454 * To avoid unnecessary object creation, this method returns the
455 * original array argument if the requested subarray length is the same
456 * and the startIndex is 0. That is to say, if the method arguments
457 * are such that the algorithm would have created a shallow clone, the
458 * original array is returned instead.
459 * </p>
460 *
461 * @throws NullArgumentException
462 *
463 * If objectArray is null.
464 *
465 * @throws ArrayIndexOutOfBoundsException
466 *
467 * If startIndex, length, or startIndex + length are out of range.
468 *
469 * @return
470 *
471 * Returns an array with the same component type as the old array.
472 *********************************************************************/
473 public static Object [ ] subArray (
474 Object [ ] objectArray,
475 int startIndex,
476 int length )
477 //////////////////////////////////////////////////////////////////////
478 {
479 NullArgumentException.check ( objectArray );
480
481 if ( ( startIndex == 0 )
482 && ( length == objectArray.length ) )
483 {
484 return objectArray;
485 }
486
487 Object [ ] newArray = ( Object [ ] ) Array.newInstance (
488 objectArray.getClass ( ).getComponentType ( ), length );
489
490 System.arraycopy ( objectArray, startIndex, newArray, 0, length );
491
492 return newArray;
493 }
494
495 /*********************************************************************
496 * Creates a new subarray from a larger array.
497 *
498 * <p>
499 * <code>
500 * <pre>
501 * return subArray (
502 * objectArray, startIndex, objectArray.length - startIndex );
503 * </pre>
504 * </code>
505 * </p>
506 *********************************************************************/
507 public static Object [ ] subArray (
508 Object [ ] objectArray,
509 int startIndex )
510 //////////////////////////////////////////////////////////////////////
511 {
512 return subArray (
513 objectArray, startIndex, objectArray.length - startIndex );
514 }
515
516 /*********************************************************************
517 * Returns the union of the arrays, discarding duplicates.
518 *********************************************************************/
519 public static Object [ ] union (
520 Object [ ] array1,
521 Object [ ] array2 )
522 //////////////////////////////////////////////////////////////////////
523 {
524 if ( array1 == null )
525 {
526 if ( array2 == null )
527 {
528 return null;
529 }
530 else
531 {
532 return removeDuplicates ( array2 );
533 }
534 }
535 else if ( array2 == null )
536 {
537 return removeDuplicates ( array1 );
538 }
539
540 Class componentType1 = array1.getClass ( ).getComponentType ( );
541
542 Class componentType2 = array2.getClass ( ).getComponentType ( );
543
544 if ( componentType1 != componentType2 )
545 {
546 throw new IllegalArgumentException (
547 "arrays of different component types" );
548 }
549
550 Hashtable hashtable = new Hashtable ( );
551
552 for ( int i = 0; i < array1.length; i++ )
553 {
554 hashtable.put ( array1 [ i ], array1 [ i ] );
555 }
556
557 for ( int i = 0; i < array2.length; i++ )
558 {
559 hashtable.put ( array2 [ i ], array2 [ i ] );
560 }
561
562 Object [ ] array = ( Object [ ] )
563 Array.newInstance ( componentType1, hashtable.size ( ) );
564
565 int index = 0;
566
567 Enumeration enumeration = hashtable.elements ( );
568
569 while ( enumeration.hasMoreElements ( ) )
570 {
571 array [ index++ ] = enumeration.nextElement ( );
572 }
573
574 return array;
575 }
576
577 //////////////////////////////////////////////////////////////////////
578 //////////////////////////////////////////////////////////////////////
579
580 private ArrayLib ( ) { }
581
582 //////////////////////////////////////////////////////////////////////
583 //////////////////////////////////////////////////////////////////////
584 }