1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @summary This class provide basic support for lambda syntax 26 * @(#) LambdaUtilities.java 27 * @author Tristan Yan 28 */ 29 30 import java.lang.reflect.Constructor; 31 import java.lang.reflect.InvocationTargetException; 32 import java.math.BigDecimal; 33 import java.nio.file.Path; 34 import java.util.*; 35 import java.util.concurrent.atomic.AtomicInteger; 36 import java.util.concurrent.atomic.AtomicLong; 37 import java.util.concurrent.atomic.AtomicReference; 38 import java.util.function.*; 39 import java.util.stream.IntStream; 40 import java.util.stream.Stream; 41 42 public class LambdaUtilities { 43 44 public static enum CharType { 45 DIGIT, LOWERCASE, UPPERCASE, SPECIAL 46 } 47 48 public static enum StringPredicateType { 49 START_WTIH, NOT_START_WITH, MORE_THAN_LEN, LESS_THAN_LEN 50 } 51 52 public static enum IntOp { 53 ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD 54 } 55 56 public static IntPredicate randomIntPredicate(boolean isUP, int limit) { 57 if (isUP) { 58 return i -> i >= limit; 59 } else { 60 return i -> i < limit; 61 } 62 } 63 64 public static Predicate<Integer> randomIntegerPredicate(boolean isUP, int limit) { 65 if (isUP) { 66 return i -> i >= limit; 67 } else { 68 return i -> i < limit; 69 } 70 } 71 72 public static LongPredicate randomLongPredicate(boolean isUP, long limit) { 73 if (isUP) { 74 return i -> i >= limit; 75 } else { 76 return i -> i < limit; 77 } 78 } 79 80 public static Predicate<Path> startPathPredicate(Path start) { 81 return p -> p.startsWith(start); 82 } 83 84 public static <T> Predicate<T> randomGenericPredicate(boolean isUp, T value, Comparator<T> c) { 85 if (isUp) { 86 return emp -> c.compare(emp, value) >= 0; 87 }else { 88 return emp -> c.compare(emp, value) < 0; 89 } 90 } 91 92 public static Predicate<StringBuilder> randomSBPredicate(StringPredicateType type, String value) { 93 switch (type) { 94 case START_WTIH: 95 return sb -> Character.isDigit(sb.charAt(0)); 96 case NOT_START_WITH: 97 return sb -> Character.isLowerCase(sb.charAt(0)); 98 case MORE_THAN_LEN: 99 return sb -> Character.isUpperCase(sb.charAt(0)); 100 default: 101 return sb -> !Character.isLetterOrDigit(sb.charAt(0)); 102 } 103 } 104 105 public static Predicate<? extends CharSequence> randomSBPredicate(CharType startType, 106 boolean first) { 107 switch (startType) { 108 case DIGIT: 109 return sb -> Character.isDigit(sb.charAt(first ? 0 : sb.toString().length() - 1)); 110 case LOWERCASE: 111 return sb -> Character.isLowerCase(sb.charAt(first ? 0 : sb.toString().length() - 1)); 112 case UPPERCASE: 113 return sb -> Character.isUpperCase(sb.charAt(first ? 0 : sb.toString().length() - 1)); 114 default: 115 return sb -> !Character.isLetterOrDigit(sb.charAt(first ? 0 : sb.toString().length() - 1)); 116 } 117 } 118 119 public static Predicate<Character> isDigitCharacterPredicate() { 120 return c -> Character.isDigit(c); 121 } 122 123 public static Function<Integer, Integer> posIntegerFunction(boolean isHighest) { 124 if (isHighest) { 125 return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; 126 } else { 127 return i -> i % 10 < 0 ? -i % 10 : i % 10; 128 } 129 } 130 131 public static Function<StringBuilder, CharType> sbGenericFunction(boolean isFirst) { 132 if (isFirst) 133 return i -> Character.isAlphabetic(i.charAt(0)) ? (Character.isUpperCase(i.charAt(0)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(0)) ? CharType.DIGIT : CharType.SPECIAL); 134 else 135 return i -> Character.isAlphabetic(i.charAt(i.length() - 1)) ? (Character.isUpperCase(i.charAt(i.length() - 1)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(i.length() - 1)) ? CharType.DIGIT : CharType.SPECIAL); 136 } 137 138 public static Function<String, Integer> mappingFunction(Map<String, Integer> m, IntOp op, int value) { 139 switch (op) { 140 case ADD: 141 return k -> (value != 0) ? m.get(k) + value : m.get(k); 142 case SUBTRACT: 143 return k -> (value != 0) ? m.get(k) - value : m.get(k); 144 case MULTIPLY: 145 return k -> (value != 0) ? m.get(k) * value : m.get(k); 146 case DIVIDE: 147 return k -> (value != 0) ? m.get(k) / value : m.get(k); 148 default: 149 return k -> (value != 0) ? m.get(k) % value : m.get(k); 150 } 151 } 152 153 public static IntFunction<Integer> posIntFunction(boolean isHighest) { 154 if (isHighest) { 155 return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; 156 } else { 157 return i -> i % 10 < 0 ? -i % 10 : i % 10; 158 } 159 } 160 161 public static BiFunction<Integer, Integer, Integer> randBetweenIntegerFunction() { 162 return (t1, t2) -> randBetween(t1, t2); 163 } 164 165 public static int randBetween(int low, int up) { 166 assert (low < up && low >= 0); 167 Random rand = new Random(); 168 int i = rand.nextInt(up); 169 while (i < low) { 170 i = rand.nextInt(); 171 } 172 return i; 173 } 174 175 public static ToIntFunction<Integer> highestPosValueIntFunction() { 176 return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; 177 } 178 179 public static ToIntFunction<Integer> lowestPosValueIntFunction() { 180 return i -> i % 10 < 0 ? -i % 10 : i % 10; 181 } 182 183 public static <T> Consumer<T> reverseConsumer(Set<T> set) { 184 return t -> { 185 set.add(t); 186 }; 187 } 188 189 public static Consumer<Integer> addIntegerConsumer(AtomicInteger ai) { 190 return t -> { 191 ai.updateAndGet(t1 -> t1 + t); 192 }; 193 } 194 195 public static Consumer<StringBuilder> appendSBConsumer(StringBuilder sb) { 196 return t -> { 197 sb.append(t); 198 }; 199 } 200 201 public static IntConsumer addIntConsumer(AtomicInteger ai) { 202 return t -> { 203 ai.updateAndGet(t1 -> t1 + t); 204 }; 205 } 206 207 public static IntConsumer addLongConsumer(AtomicLong ai) { 208 return t -> { 209 ai.updateAndGet(t1 -> t1 + t); 210 }; 211 } 212 213 public static <T> Consumer<T> copyConsumer(List<T> list) { 214 return t -> { 215 list.add(t); 216 }; 217 } 218 219 public static <T> Consumer<T> existsConsumer(Collection<T> in, Collection<T> out) { 220 return t -> { 221 if (in.contains(t)) { 222 out.add(t); 223 } 224 }; 225 } 226 227 public static Supplier<StringBuilder> sbSupplier(StringBuilder value) { 228 return () -> value; 229 } 230 231 public static Supplier<Integer> integerSupplier(int value) { 232 return () -> value; 233 } 234 235 public static <T> Supplier<T> genericSuppiler(T value) { 236 return () -> value; 237 } 238 239 public static IntSupplier intSupplier(int value) { 240 return () -> value; 241 } 242 243 public static Supplier<Long> longSupplier(long value) { 244 return () -> value; 245 } 246 247 public static Supplier<AtomicInteger> atomicIntegerSupplier(int value) { 248 return () -> new AtomicInteger(value); 249 } 250 251 public static <T> Supplier<AtomicReference<T>> atomicGenericSupplier(T value) { 252 return () -> new AtomicReference<>(value); 253 } 254 255 public static Supplier<AtomicReference<StringBuilder>> atomicSBSupplier(StringBuilder value) { 256 return () -> new AtomicReference<>(value); 257 } 258 259 public static UnaryOperator<Integer> opIntegerUnaryOperator(IntOp op, int value) { 260 switch (op) { 261 case ADD: 262 return t -> t + value; 263 case SUBTRACT: 264 return t -> t - value; 265 case MULTIPLY: 266 return t -> t * value; 267 case DIVIDE: 268 return t -> t / value; 269 default: 270 return t -> t % value; 271 } 272 } 273 274 public static IntUnaryOperator opIntUnaryOperator(IntOp op, int value) { 275 if(value == 0) 276 return t -> t; 277 switch (op) { 278 case ADD: 279 return t -> t + value; 280 case SUBTRACT: 281 return t -> t - value; 282 case MULTIPLY: 283 return t -> t * value; 284 case DIVIDE: 285 return t -> t / value; 286 default: 287 return t -> t % value; 288 } 289 } 290 291 public static Function<Integer, Integer> opIntegerFunction(IntOp op, int value) { 292 if(value == 0) 293 return t -> t; 294 switch (op) { 295 case ADD: 296 return t -> Integer.valueOf(t + value); 297 case SUBTRACT: 298 return t -> Integer.valueOf(t - value); 299 case MULTIPLY: 300 return t -> Integer.valueOf(t * value); 301 case DIVIDE: 302 return t -> Integer.valueOf(t / value); 303 default: 304 return t -> Integer.valueOf(t % value); 305 } 306 } 307 308 public static ToIntFunction<Integer> opToIntFunction(IntOp op, int value) { 309 if(value == 0) 310 return t -> t.intValue(); 311 switch (op) { 312 case ADD: 313 return t -> t.intValue() + value; 314 case SUBTRACT: 315 return t -> t.intValue() - value; 316 case MULTIPLY: 317 return t -> t.intValue() * value; 318 case DIVIDE: 319 return t -> t.intValue() / value; 320 default: 321 return t -> t.intValue() % value; 322 } 323 } 324 325 public static IntFunction<Integer> opIntFunction(IntOp op, int value) { 326 if(value == 0) 327 return t -> t; 328 switch (op) { 329 case ADD: 330 return t -> t + value; 331 case SUBTRACT: 332 return t -> t - value; 333 case MULTIPLY: 334 return t -> t * value; 335 case DIVIDE: 336 return t -> t / value; 337 default: 338 return t -> t % value; 339 } 340 } 341 342 public static IntUnaryOperator addIntUnaryOperator(int value) { 343 return t -> t + value; 344 } 345 346 public static IntUnaryOperator subIntUnaryOperator(int value) { 347 return t -> t - value; 348 } 349 350 public static IntUnaryOperator mulIntUnaryOperator(int value) { 351 return t -> t * value; 352 } 353 354 public static IntUnaryOperator divIntUnaryOperator(int value) { 355 return t -> t / value; 356 } 357 358 public static IntBinaryOperator minIntBinaryOperator() { 359 return (t1, t2) -> t1< t2 ? t1 : t2; 360 } 361 362 public static BinaryOperator<Integer> minIntegerBinaryOperator(Comparator<Integer> c) { 363 return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2; 364 } 365 366 public static <T>BinaryOperator<T> minGenericBinaryOperator(Comparator<T> c) { 367 return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2; 368 } 369 370 public static BinaryOperator<StringBuilder> minSBBinaryOperator(Comparator<StringBuilder> c) { 371 return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t1 : t2; 372 } 373 374 public static IntBinaryOperator maxIntBinaryOperator() { 375 return ( t1, t2 ) -> (t1< t2) ? t2: t1; 376 } 377 378 public static BinaryOperator<Integer> maxIntegerBinaryOperator(Comparator<Integer> c) { 379 return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1; 380 } 381 382 public static <T> BinaryOperator<T> maxGenericBinaryOperator(Comparator<T> c) { 383 return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1; 384 } 385 386 public static IntBinaryOperator maxIntBinaryOperator(Comparator<Integer> c) { 387 return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1; 388 } 389 390 public static BinaryOperator<StringBuilder> maxSBBinaryOperator(Comparator<StringBuilder> c) { 391 return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1; 392 } 393 394 public static BinaryOperator<Integer> addIntegerBinaryOperator() { 395 return ( t1 , t2 ) -> t1 + t2; 396 } 397 398 public static IntBinaryOperator addIntBinaryOperator() { 399 return ( t1 , t2 ) -> t1 + t2; 400 } 401 402 public static BinaryOperator<BigDecimal> addBigDecimalBinaryOperator() { 403 return ( t1 , t2 ) -> t1.add(t2); 404 } 405 406 public static DoubleBinaryOperator addDoubleBinaryOperator() { 407 return ( t1 , t2 ) -> t1 + t2; 408 } 409 410 public static BinaryOperator<StringBuilder> appendSBBinaryOperator() { 411 return (t1 , t2) -> new StringBuilder().append(t1).append(t2); 412 } 413 414 public static BinaryOperator<Integer> subIntegerBinaryOperator() { 415 return (t1, t2) -> t1 - t2; 416 } 417 418 public static IntBinaryOperator subIntBinaryOperator() { 419 return (t1, t2) -> t1 - t2; 420 } 421 422 public static BinaryOperator<StringBuilder> deleteSBBinaryOperator() { 423 return (t1, t2) -> {if (t1.length() >= t2.length()) { 424 int i1 = t1.indexOf(t2.toString()); 425 int i2 = i1 + t2.length(); 426 return new StringBuilder(t1).delete(i1, i2); 427 }else { 428 int i1 = t2.indexOf(t1.toString()); 429 int i2 = i1 + t1.length(); 430 return new StringBuilder(t2).delete(i1, i2); 431 } 432 }; 433 434 } 435 436 public static IntBinaryOperator mulIntBinaryOperator() { 437 return (t1, t2) -> t1 * t2; 438 } 439 440 public static IntBinaryOperator divIntBinaryOperator() { 441 return (t1, t2) -> t1 / t2; 442 } 443 444 public static LongUnaryOperator addLongUnaryOperator(long value) { 445 return t -> t + value; 446 } 447 448 public static UnaryOperator<StringBuilder> appendSBUnaryOperator(StringBuilder value) { 449 return t -> t.append(value); 450 } 451 452 public static LongUnaryOperator subLongUnaryOperator(long value) { 453 return t -> t - value; 454 } 455 456 public static LongUnaryOperator mulLongUnaryOperator(long value) { 457 return t -> t * value; 458 } 459 460 public static LongUnaryOperator divLongUnaryOperator(long value) { 461 return t -> t / value; 462 } 463 464 public static LongBinaryOperator addLongBinaryOperator() { 465 return (t1, t2) -> t1 + t2; 466 } 467 468 public static LongBinaryOperator subLongBinaryOperator() { 469 return (t1, t2) -> t1 - t2; 470 } 471 472 public static LongBinaryOperator mulLongBinaryOperator() { 473 return (t1, t2) -> t1 * t2; 474 } 475 476 public static LongBinaryOperator divLongBinaryOperator() { 477 return (t1, t2) -> t1 / t2; 478 } 479 480 public static BiConsumer<AtomicInteger, Integer> addIntegerBiConsumer() { 481 return (t1 , t2 ) -> { t1.addAndGet(t2); }; 482 } 483 484 public static BiConsumer<AtomicInteger, AtomicInteger> addAtomicIntegerBiConsumer() { 485 return (t1 , t2) -> { t1.addAndGet(t2.get()); }; 486 } 487 488 public static BiConsumer<AtomicReference<StringBuilder>, StringBuilder> appendSBBiConsumer() { 489 return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2));}; 490 } 491 492 public static BiConsumer<AtomicReference<StringBuilder>, AtomicReference<StringBuilder>> appendAtomicSBBiConsumer() { 493 return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2.get()));}; 494 } 495 496 public static BiConsumer<AtomicInteger, Integer> maxIntegerBiConsumer(Comparator<Integer> c) { 497 return (t1 , t2 ) -> { t1.getAndUpdate(t -> max(t, t2, c)); }; 498 } 499 500 public static <T> BiConsumer<AtomicReference<T>, T> maxGenericBiConsumer(Comparator<T> c) { 501 return (t1 , t2 ) -> { t1.getAndUpdate(t -> max(t, t2, c)); }; 502 } 503 504 public static BiConsumer<AtomicInteger, AtomicInteger> maxAtomicIntegerBiConsumer(Comparator<Integer> c) { 505 return (t1 , t2) -> { t1.getAndUpdate(t -> max(t, t2.get(), c)); }; 506 } 507 508 public static <T> BiConsumer<AtomicReference<T>, AtomicReference<T>> maxAtomicGenericBiConsumer(Comparator<T> c) { 509 return (t1 , t2) -> { t1.getAndUpdate(t -> max(t, t2.get(), c)); }; 510 } 511 512 public static BiConsumer<AtomicInteger, Integer> minIntegerBiConsumer(Comparator<Integer> c) { 513 return (t1 , t2) -> { t1.getAndUpdate(t -> min(t, t2, c)); }; 514 } 515 516 public static <T> BiConsumer<AtomicReference<T>, T> minGenericBiConsumer(Comparator<T> c) { 517 return (t1 , t2) -> { t1.getAndUpdate(t -> min(t, t2, c)); }; 518 } 519 520 public static BiConsumer<AtomicInteger, AtomicInteger> minAtomicIntegerBiConsumer(Comparator<Integer> c) { 521 return (t1, t2) -> { t1.getAndUpdate(t -> min(t, t2.get(), c)); }; 522 } 523 524 public static <T> BiConsumer<AtomicReference<T>, AtomicReference<T>> minAtomicGenericBiConsumer(Comparator<T> c) { 525 return (t1, t2) -> { t1.getAndUpdate(t -> min(t, t2.get(), c)); }; 526 } 527 528 public static BiFunction<Integer, Integer, Integer> maxIntegerFunction(Comparator<Integer> c) { 529 return (t1, t2) -> max(t1, t2, c); 530 } 531 532 public static BiFunction<BigDecimal, Integer, BigDecimal> deviationSequareFunction(double avg) { 533 return (bd, t) -> bd.add(new BigDecimal(avg - t).pow(2)); 534 } 535 536 public static <T> BiFunction<T, T, T> maxGenericFunction(Comparator<T> c) { 537 return (t1, t2) -> max(t1, t2, c); 538 } 539 540 public static BiFunction<StringBuilder, StringBuilder, StringBuilder> maxStringBuilderFunction(Comparator<StringBuilder> c) { 541 return (t1, t2) -> max(t1, t2, c); 542 } 543 544 public static BiFunction<Integer, Integer, Integer> minIntegerFunction(Comparator<Integer> c) { 545 return (t1, t2) -> min(t1, t2, c); 546 } 547 548 public static <T> BiFunction<T, T, T> minGenericFunction(Comparator<T> c) { 549 return (t1, t2) -> min(t1, t2, c); 550 } 551 552 public static BiFunction<StringBuilder, StringBuilder, StringBuilder> minStringBuilderFunction(Comparator<StringBuilder> c) { 553 return (t1, t2) -> min(t1, t2, c); 554 } 555 556 public static BiFunction<String, Integer, Integer> opBiFunction(IntOp op, int value) { 557 switch (op) { 558 case ADD: 559 return (k, v) -> (value != 0) ? v + value : v; 560 case SUBTRACT: 561 return (k, v) -> (value != 0) ? v - value : v; 562 case MULTIPLY: 563 return (k, v) -> (value != 0) ? v * value : v; 564 case DIVIDE: 565 return (k, v) -> (value != 0) ? v / value : v; 566 default: 567 return (k, v) -> (value != 0) ? v % value : v; 568 } 569 } 570 571 572 public static BiFunction<Integer, Integer, Integer> opBiFunction(IntOp op) { 573 switch (op) { 574 case ADD: 575 return (oldv, v) -> (v != 0) ? oldv + v : oldv; 576 case SUBTRACT: 577 return (oldv, v) -> (v != 0) ? oldv - v : oldv; 578 case MULTIPLY: 579 return (oldv, v) -> (v != 0) ? oldv * v : oldv; 580 case DIVIDE: 581 return (oldv, v) -> (v != 0) ? oldv / v : oldv; 582 default: 583 return (oldv, v) -> (v != 0) ? oldv % v : oldv; 584 } 585 } 586 587 private static Integer min(Integer i1, Integer i2, Comparator<Integer> c) { 588 return c.compare(i1, i2) < 0 ? i1 : i2; 589 } 590 591 private static <T> T min(T i1, T i2, Comparator<T> c) { 592 return c.compare(i1, i2) < 0 ? i1 : i2; 593 } 594 595 private static StringBuilder min(StringBuilder sb1, StringBuilder sb2, Comparator<StringBuilder> c) { 596 return c.compare(sb1, sb2) < 0 ? sb1 : sb2; 597 } 598 599 private static Integer max(Integer i1, Integer i2, Comparator<Integer> c) { 600 return c.compare(i1, i2) < 0 ? i2 : i1; 601 } 602 603 private static <T> T max(T i1, T i2, Comparator<T> c) { 604 return c.compare(i1, i2) < 0 ? i2 : i1; 605 } 606 607 private static StringBuilder max(StringBuilder sb1, StringBuilder sb2, Comparator<StringBuilder> c) { 608 return c.compare(sb1, sb2) < 0 ? sb2 : sb1; 609 } 610 /* 611 * Construct a Collection C object based on a C object, using generic type 612 * instead of Class type can help preventing type error in compilation 613 */ 614 @SuppressWarnings({"rawtypes", "unchecked"}) 615 public static <E, C extends Collection<E>> C create(C c, int... initSize) 616 throws InstantiationException, IllegalAccessException, 617 NoSuchMethodException, IllegalArgumentException, 618 InvocationTargetException { 619 return create((Class<C>) c.getClass(), initSize); 620 } 621 622 /* 623 * Construct a Collection C object based on a C's type, using generic type 624 * instead of Class type can help preventing type error in compilation 625 */ 626 @SuppressWarnings({"rawtypes", "unchecked"}) 627 public static <E, T extends Collection<E>> T create( 628 Class<? extends Collection<E>> cls, int... initSize) 629 throws InstantiationException, IllegalAccessException, 630 NoSuchMethodException, IllegalArgumentException, 631 InvocationTargetException { 632 assert (initSize.length <= 1); 633 Collection<E> c; 634 if (initSize.length == 0) { 635 c = cls.newInstance(); 636 } else { 637 Constructor con = cls.getConstructor(int.class); 638 c = (Collection<E>) con.newInstance(initSize[0]); 639 } 640 return (T) c; 641 } 642 643 /* 644 * Construct a T object based on T's type, using generic type instead of 645 * Class type can help preventing type error in compilation 646 */ 647 @SuppressWarnings({"rawtypes", "unchecked"}) 648 public static <K, V, M extends Map<K, V>> M createMap(M m, int... initSize) 649 throws InstantiationException, IllegalAccessException, 650 NoSuchMethodException, IllegalArgumentException, 651 InvocationTargetException { 652 return createMap((Class<M>) m.getClass(), initSize); 653 } 654 655 /* 656 * Construct a Map M object based on M's type, using generic type instead of 657 * Class type can help preventing type error in compilation 658 */ 659 @SuppressWarnings({"rawtypes", "unchecked"}) 660 public static <K, V, M extends Map<K, V>> M createMap(Class<? extends Map<K, V>> cls, 661 int... initSize) throws InstantiationException, 662 IllegalAccessException, NoSuchMethodException, 663 IllegalArgumentException, InvocationTargetException { 664 assert (initSize.length <= 1); 665 Map<K, V> map; 666 if (initSize.length == 0) { 667 map = cls.newInstance(); 668 } else { 669 Constructor con = cls.getConstructor(int.class); 670 map = (Map<K, V>) con.newInstance(initSize[0]); 671 } 672 return (M) map; 673 } 674 }