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="https://www.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 }