001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4; 018 019import java.io.PrintStream; 020import java.text.NumberFormat; 021import java.text.ParseException; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.Enumeration; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Map.Entry; 029import java.util.Properties; 030import java.util.ResourceBundle; 031import java.util.SortedMap; 032import java.util.TreeMap; 033 034import org.apache.commons.collections4.map.AbstractMapDecorator; 035import org.apache.commons.collections4.map.AbstractSortedMapDecorator; 036import org.apache.commons.collections4.map.FixedSizeMap; 037import org.apache.commons.collections4.map.FixedSizeSortedMap; 038import org.apache.commons.collections4.map.LazyMap; 039import org.apache.commons.collections4.map.LazySortedMap; 040import org.apache.commons.collections4.map.ListOrderedMap; 041import org.apache.commons.collections4.map.MultiValueMap; 042import org.apache.commons.collections4.map.PredicatedMap; 043import org.apache.commons.collections4.map.PredicatedSortedMap; 044import org.apache.commons.collections4.map.TransformedMap; 045import org.apache.commons.collections4.map.TransformedSortedMap; 046import org.apache.commons.collections4.map.UnmodifiableMap; 047import org.apache.commons.collections4.map.UnmodifiableSortedMap; 048 049/** 050 * Provides utility methods and decorators for 051 * {@link Map} and {@link SortedMap} instances. 052 * <p> 053 * It contains various type safe methods 054 * as well as other useful features like deep copying. 055 * <p> 056 * It also provides the following decorators: 057 * 058 * <ul> 059 * <li>{@link #fixedSizeMap(Map)} 060 * <li>{@link #fixedSizeSortedMap(SortedMap)} 061 * <li>{@link #lazyMap(Map,Factory)} 062 * <li>{@link #lazyMap(Map,Transformer)} 063 * <li>{@link #lazySortedMap(SortedMap,Factory)} 064 * <li>{@link #lazySortedMap(SortedMap,Transformer)} 065 * <li>{@link #predicatedMap(Map,Predicate,Predicate)} 066 * <li>{@link #predicatedSortedMap(SortedMap,Predicate,Predicate)} 067 * <li>{@link #transformedMap(Map, Transformer, Transformer)} 068 * <li>{@link #transformedSortedMap(SortedMap, Transformer, Transformer)} 069 * <li>{@link #multiValueMap( Map )} 070 * <li>{@link #multiValueMap( Map, Class )} 071 * <li>{@link #multiValueMap( Map, Factory )} 072 * </ul> 073 * 074 * @since 1.0 075 * @version $Id: MapUtils.html 972421 2015-11-14 20:00:04Z tn $ 076 */ 077public class MapUtils { 078 079 /** 080 * An empty unmodifiable sorted map. 081 * This is not provided in the JDK. 082 */ 083 @SuppressWarnings("rawtypes") 084 public static final SortedMap EMPTY_SORTED_MAP = 085 UnmodifiableSortedMap.unmodifiableSortedMap(new TreeMap<Object, Object>()); 086 087 /** 088 * String used to indent the verbose and debug Map prints. 089 */ 090 private static final String INDENT_STRING = " "; 091 092 /** 093 * <code>MapUtils</code> should not normally be instantiated. 094 */ 095 private MapUtils() {} 096 097 // Type safe getters 098 //------------------------------------------------------------------------- 099 /** 100 * Gets from a Map in a null-safe manner. 101 * 102 * @param <K> the key type 103 * @param <V> the value type 104 * @param map the map to use 105 * @param key the key to look up 106 * @return the value in the Map, <code>null</code> if null map input 107 */ 108 public static <K, V> V getObject(final Map<? super K, V> map, final K key) { 109 if (map != null) { 110 return map.get(key); 111 } 112 return null; 113 } 114 115 /** 116 * Gets a String from a Map in a null-safe manner. 117 * <p> 118 * The String is obtained via <code>toString</code>. 119 * 120 * @param <K> the key type 121 * @param map the map to use 122 * @param key the key to look up 123 * @return the value in the Map as a String, <code>null</code> if null map input 124 */ 125 public static <K> String getString(final Map<? super K, ?> map, final K key) { 126 if (map != null) { 127 final Object answer = map.get(key); 128 if (answer != null) { 129 return answer.toString(); 130 } 131 } 132 return null; 133 } 134 135 /** 136 * Gets a Boolean from a Map in a null-safe manner. 137 * <p> 138 * If the value is a <code>Boolean</code> it is returned directly. 139 * If the value is a <code>String</code> and it equals 'true' ignoring case 140 * then <code>true</code> is returned, otherwise <code>false</code>. 141 * If the value is a <code>Number</code> an integer zero value returns 142 * <code>false</code> and non-zero returns <code>true</code>. 143 * Otherwise, <code>null</code> is returned. 144 * 145 * @param <K> the key type 146 * @param map the map to use 147 * @param key the key to look up 148 * @return the value in the Map as a Boolean, <code>null</code> if null map input 149 */ 150 public static <K> Boolean getBoolean(final Map<? super K, ?> map, final K key) { 151 if (map != null) { 152 final Object answer = map.get(key); 153 if (answer != null) { 154 if (answer instanceof Boolean) { 155 return (Boolean) answer; 156 } 157 if (answer instanceof String) { 158 return Boolean.valueOf((String) answer); 159 } 160 if (answer instanceof Number) { 161 final Number n = (Number) answer; 162 return n.intValue() != 0 ? Boolean.TRUE : Boolean.FALSE; 163 } 164 } 165 } 166 return null; 167 } 168 169 /** 170 * Gets a Number from a Map in a null-safe manner. 171 * <p> 172 * If the value is a <code>Number</code> it is returned directly. 173 * If the value is a <code>String</code> it is converted using 174 * {@link NumberFormat#parse(String)} on the system default formatter 175 * returning <code>null</code> if the conversion fails. 176 * Otherwise, <code>null</code> is returned. 177 * 178 * @param <K> the key type 179 * @param map the map to use 180 * @param key the key to look up 181 * @return the value in the Map as a Number, <code>null</code> if null map input 182 */ 183 public static <K> Number getNumber(final Map<? super K, ?> map, final K key) { 184 if (map != null) { 185 final Object answer = map.get(key); 186 if (answer != null) { 187 if (answer instanceof Number) { 188 return (Number) answer; 189 } 190 if (answer instanceof String) { 191 try { 192 final String text = (String) answer; 193 return NumberFormat.getInstance().parse(text); 194 } catch (final ParseException e) { // NOPMD 195 // failure means null is returned 196 } 197 } 198 } 199 } 200 return null; 201 } 202 203 /** 204 * Gets a Byte from a Map in a null-safe manner. 205 * <p> 206 * The Byte is obtained from the results of {@link #getNumber(Map,Object)}. 207 * 208 * @param <K> the key type 209 * @param map the map to use 210 * @param key the key to look up 211 * @return the value in the Map as a Byte, <code>null</code> if null map input 212 */ 213 public static <K> Byte getByte(final Map<? super K, ?> map, final K key) { 214 final Number answer = getNumber(map, key); 215 if (answer == null) { 216 return null; 217 } 218 if (answer instanceof Byte) { 219 return (Byte) answer; 220 } 221 return Byte.valueOf(answer.byteValue()); 222 } 223 224 /** 225 * Gets a Short from a Map in a null-safe manner. 226 * <p> 227 * The Short is obtained from the results of {@link #getNumber(Map,Object)}. 228 * 229 * @param <K> the key type 230 * @param map the map to use 231 * @param key the key to look up 232 * @return the value in the Map as a Short, <code>null</code> if null map input 233 */ 234 public static <K> Short getShort(final Map<? super K, ?> map, final K key) { 235 final Number answer = getNumber(map, key); 236 if (answer == null) { 237 return null; 238 } 239 if (answer instanceof Short) { 240 return (Short) answer; 241 } 242 return Short.valueOf(answer.shortValue()); 243 } 244 245 /** 246 * Gets a Integer from a Map in a null-safe manner. 247 * <p> 248 * The Integer is obtained from the results of {@link #getNumber(Map,Object)}. 249 * 250 * @param <K> the key type 251 * @param map the map to use 252 * @param key the key to look up 253 * @return the value in the Map as a Integer, <code>null</code> if null map input 254 */ 255 public static <K> Integer getInteger(final Map<? super K, ?> map, final K key) { 256 final Number answer = getNumber(map, key); 257 if (answer == null) { 258 return null; 259 } 260 if (answer instanceof Integer) { 261 return (Integer) answer; 262 } 263 return Integer.valueOf(answer.intValue()); 264 } 265 266 /** 267 * Gets a Long from a Map in a null-safe manner. 268 * <p> 269 * The Long is obtained from the results of {@link #getNumber(Map,Object)}. 270 * 271 * @param <K> the key type 272 * @param map the map to use 273 * @param key the key to look up 274 * @return the value in the Map as a Long, <code>null</code> if null map input 275 */ 276 public static <K> Long getLong(final Map<? super K, ?> map, final K key) { 277 final Number answer = getNumber(map, key); 278 if (answer == null) { 279 return null; 280 } 281 if (answer instanceof Long) { 282 return (Long) answer; 283 } 284 return Long.valueOf(answer.longValue()); 285 } 286 287 /** 288 * Gets a Float from a Map in a null-safe manner. 289 * <p> 290 * The Float is obtained from the results of {@link #getNumber(Map,Object)}. 291 * 292 * @param <K> the key type 293 * @param map the map to use 294 * @param key the key to look up 295 * @return the value in the Map as a Float, <code>null</code> if null map input 296 */ 297 public static <K> Float getFloat(final Map<? super K, ?> map, final K key) { 298 final Number answer = getNumber(map, key); 299 if (answer == null) { 300 return null; 301 } 302 if (answer instanceof Float) { 303 return (Float) answer; 304 } 305 return Float.valueOf(answer.floatValue()); 306 } 307 308 /** 309 * Gets a Double from a Map in a null-safe manner. 310 * <p> 311 * The Double is obtained from the results of {@link #getNumber(Map,Object)}. 312 * 313 * @param <K> the key type 314 * @param map the map to use 315 * @param key the key to look up 316 * @return the value in the Map as a Double, <code>null</code> if null map input 317 */ 318 public static <K> Double getDouble(final Map<? super K, ?> map, final K key) { 319 final Number answer = getNumber(map, key); 320 if (answer == null) { 321 return null; 322 } 323 if (answer instanceof Double) { 324 return (Double) answer; 325 } 326 return Double.valueOf(answer.doubleValue()); 327 } 328 329 /** 330 * Gets a Map from a Map in a null-safe manner. 331 * <p> 332 * If the value returned from the specified map is not a Map then 333 * <code>null</code> is returned. 334 * 335 * @param <K> the key type 336 * @param map the map to use 337 * @param key the key to look up 338 * @return the value in the Map as a Map, <code>null</code> if null map input 339 */ 340 public static <K> Map<?, ?> getMap(final Map<? super K, ?> map, final K key) { 341 if (map != null) { 342 final Object answer = map.get(key); 343 if (answer != null && answer instanceof Map) { 344 return (Map<?, ?>) answer; 345 } 346 } 347 return null; 348 } 349 350 // Type safe getters with default values 351 //------------------------------------------------------------------------- 352 /** 353 * Looks up the given key in the given map, converting null into the 354 * given default value. 355 * 356 * @param <K> the key type 357 * @param <V> the value type 358 * @param map the map whose value to look up 359 * @param key the key of the value to look up in that map 360 * @param defaultValue what to return if the value is null 361 * @return the value in the map, or defaultValue if the original value 362 * is null or the map is null 363 */ 364 public static <K, V> V getObject(final Map<K, V> map, final K key, final V defaultValue) { 365 if (map != null) { 366 final V answer = map.get(key); 367 if (answer != null) { 368 return answer; 369 } 370 } 371 return defaultValue; 372 } 373 374 /** 375 * Looks up the given key in the given map, converting the result into 376 * a string, using the default value if the the conversion fails. 377 * 378 * @param <K> the key type 379 * @param map the map whose value to look up 380 * @param key the key of the value to look up in that map 381 * @param defaultValue what to return if the value is null or if the 382 * conversion fails 383 * @return the value in the map as a string, or defaultValue if the 384 * original value is null, the map is null or the string conversion fails 385 */ 386 public static <K> String getString(final Map<? super K, ?> map, final K key, final String defaultValue) { 387 String answer = getString(map, key); 388 if (answer == null) { 389 answer = defaultValue; 390 } 391 return answer; 392 } 393 394 /** 395 * Looks up the given key in the given map, converting the result into 396 * a boolean, using the default value if the the conversion fails. 397 * 398 * @param <K> the key type 399 * @param map the map whose value to look up 400 * @param key the key of the value to look up in that map 401 * @param defaultValue what to return if the value is null or if the 402 * conversion fails 403 * @return the value in the map as a boolean, or defaultValue if the 404 * original value is null, the map is null or the boolean conversion fails 405 */ 406 public static <K> Boolean getBoolean(final Map<? super K, ?> map, final K key, final Boolean defaultValue) { 407 Boolean answer = getBoolean(map, key); 408 if (answer == null) { 409 answer = defaultValue; 410 } 411 return answer; 412 } 413 414 /** 415 * Looks up the given key in the given map, converting the result into 416 * a number, using the default value if the the conversion fails. 417 * 418 * @param <K> the key type 419 * @param map the map whose value to look up 420 * @param key the key of the value to look up in that map 421 * @param defaultValue what to return if the value is null or if the 422 * conversion fails 423 * @return the value in the map as a number, or defaultValue if the 424 * original value is null, the map is null or the number conversion fails 425 */ 426 public static <K> Number getNumber(final Map<? super K, ?> map, final K key, final Number defaultValue) { 427 Number answer = getNumber(map, key); 428 if (answer == null) { 429 answer = defaultValue; 430 } 431 return answer; 432 } 433 434 /** 435 * Looks up the given key in the given map, converting the result into 436 * a byte, using the default value if the the conversion fails. 437 * 438 * @param <K> the key type 439 * @param map the map whose value to look up 440 * @param key the key of the value to look up in that map 441 * @param defaultValue what to return if the value is null or if the 442 * conversion fails 443 * @return the value in the map as a number, or defaultValue if the 444 * original value is null, the map is null or the number conversion fails 445 */ 446 public static <K> Byte getByte(final Map<? super K, ?> map, final K key, final Byte defaultValue) { 447 Byte answer = getByte(map, key); 448 if (answer == null) { 449 answer = defaultValue; 450 } 451 return answer; 452 } 453 454 /** 455 * Looks up the given key in the given map, converting the result into 456 * a short, using the default value if the the conversion fails. 457 * 458 * @param <K> the key type 459 * @param map the map whose value to look up 460 * @param key the key of the value to look up in that map 461 * @param defaultValue what to return if the value is null or if the 462 * conversion fails 463 * @return the value in the map as a number, or defaultValue if the 464 * original value is null, the map is null or the number conversion fails 465 */ 466 public static <K> Short getShort(final Map<? super K, ?> map, final K key, final Short defaultValue) { 467 Short answer = getShort(map, key); 468 if (answer == null) { 469 answer = defaultValue; 470 } 471 return answer; 472 } 473 474 /** 475 * Looks up the given key in the given map, converting the result into 476 * an integer, using the default value if the the conversion fails. 477 * 478 * @param <K> the key type 479 * @param map the map whose value to look up 480 * @param key the key of the value to look up in that map 481 * @param defaultValue what to return if the value is null or if the 482 * conversion fails 483 * @return the value in the map as a number, or defaultValue if the 484 * original value is null, the map is null or the number conversion fails 485 */ 486 public static <K> Integer getInteger(final Map<? super K, ?> map, final K key, final Integer defaultValue) { 487 Integer answer = getInteger(map, key); 488 if (answer == null) { 489 answer = defaultValue; 490 } 491 return answer; 492 } 493 494 /** 495 * Looks up the given key in the given map, converting the result into 496 * a long, using the default value if the the conversion fails. 497 * 498 * @param <K> the key type 499 * @param map the map whose value to look up 500 * @param key the key of the value to look up in that map 501 * @param defaultValue what to return if the value is null or if the 502 * conversion fails 503 * @return the value in the map as a number, or defaultValue if the 504 * original value is null, the map is null or the number conversion fails 505 */ 506 public static <K> Long getLong(final Map<? super K, ?> map, final K key, final Long defaultValue) { 507 Long answer = getLong(map, key); 508 if (answer == null) { 509 answer = defaultValue; 510 } 511 return answer; 512 } 513 514 /** 515 * Looks up the given key in the given map, converting the result into 516 * a float, using the default value if the the conversion fails. 517 * 518 * @param <K> the key type 519 * @param map the map whose value to look up 520 * @param key the key of the value to look up in that map 521 * @param defaultValue what to return if the value is null or if the 522 * conversion fails 523 * @return the value in the map as a number, or defaultValue if the 524 * original value is null, the map is null or the number conversion fails 525 */ 526 public static <K> Float getFloat(final Map<? super K, ?> map, final K key, final Float defaultValue) { 527 Float answer = getFloat(map, key); 528 if (answer == null) { 529 answer = defaultValue; 530 } 531 return answer; 532 } 533 534 /** 535 * Looks up the given key in the given map, converting the result into 536 * a double, using the default value if the the conversion fails. 537 * 538 * @param <K> the key type 539 * @param map the map whose value to look up 540 * @param key the key of the value to look up in that map 541 * @param defaultValue what to return if the value is null or if the 542 * conversion fails 543 * @return the value in the map as a number, or defaultValue if the 544 * original value is null, the map is null or the number conversion fails 545 */ 546 public static <K> Double getDouble(final Map<? super K, ?> map, final K key, final Double defaultValue) { 547 Double answer = getDouble(map, key); 548 if (answer == null) { 549 answer = defaultValue; 550 } 551 return answer; 552 } 553 554 /** 555 * Looks up the given key in the given map, converting the result into 556 * a map, using the default value if the the conversion fails. 557 * 558 * @param <K> the key type 559 * @param map the map whose value to look up 560 * @param key the key of the value to look up in that map 561 * @param defaultValue what to return if the value is null or if the 562 * conversion fails 563 * @return the value in the map as a number, or defaultValue if the 564 * original value is null, the map is null or the map conversion fails 565 */ 566 public static <K> Map<?, ?> getMap(final Map<? super K, ?> map, final K key, final Map<?, ?> defaultValue) { 567 Map<?, ?> answer = getMap(map, key); 568 if (answer == null) { 569 answer = defaultValue; 570 } 571 return answer; 572 } 573 574 // Type safe primitive getters 575 //------------------------------------------------------------------------- 576 /** 577 * Gets a boolean from a Map in a null-safe manner. 578 * <p> 579 * If the value is a <code>Boolean</code> its value is returned. 580 * If the value is a <code>String</code> and it equals 'true' ignoring case 581 * then <code>true</code> is returned, otherwise <code>false</code>. 582 * If the value is a <code>Number</code> an integer zero value returns 583 * <code>false</code> and non-zero returns <code>true</code>. 584 * Otherwise, <code>false</code> is returned. 585 * 586 * @param <K> the key type 587 * @param map the map to use 588 * @param key the key to look up 589 * @return the value in the Map as a Boolean, <code>false</code> if null map input 590 */ 591 public static <K> boolean getBooleanValue(final Map<? super K, ?> map, final K key) { 592 return Boolean.TRUE.equals(getBoolean(map, key)); 593 } 594 595 /** 596 * Gets a byte from a Map in a null-safe manner. 597 * <p> 598 * The byte is obtained from the results of {@link #getNumber(Map,Object)}. 599 * 600 * @param <K> the key type 601 * @param map the map to use 602 * @param key the key to look up 603 * @return the value in the Map as a byte, <code>0</code> if null map input 604 */ 605 public static <K> byte getByteValue(final Map<? super K, ?> map, final K key) { 606 final Byte byteObject = getByte(map, key); 607 if (byteObject == null) { 608 return 0; 609 } 610 return byteObject.byteValue(); 611 } 612 613 /** 614 * Gets a short from a Map in a null-safe manner. 615 * <p> 616 * The short is obtained from the results of {@link #getNumber(Map,Object)}. 617 * 618 * @param <K> the key type 619 * @param map the map to use 620 * @param key the key to look up 621 * @return the value in the Map as a short, <code>0</code> if null map input 622 */ 623 public static <K> short getShortValue(final Map<? super K, ?> map, final K key) { 624 final Short shortObject = getShort(map, key); 625 if (shortObject == null) { 626 return 0; 627 } 628 return shortObject.shortValue(); 629 } 630 631 /** 632 * Gets an int from a Map in a null-safe manner. 633 * <p> 634 * The int is obtained from the results of {@link #getNumber(Map,Object)}. 635 * 636 * @param <K> the key type 637 * @param map the map to use 638 * @param key the key to look up 639 * @return the value in the Map as an int, <code>0</code> if null map input 640 */ 641 public static <K> int getIntValue(final Map<? super K, ?> map, final K key) { 642 final Integer integerObject = getInteger(map, key); 643 if (integerObject == null) { 644 return 0; 645 } 646 return integerObject.intValue(); 647 } 648 649 /** 650 * Gets a long from a Map in a null-safe manner. 651 * <p> 652 * The long is obtained from the results of {@link #getNumber(Map,Object)}. 653 * 654 * @param <K> the key type 655 * @param map the map to use 656 * @param key the key to look up 657 * @return the value in the Map as a long, <code>0L</code> if null map input 658 */ 659 public static <K> long getLongValue(final Map<? super K, ?> map, final K key) { 660 final Long longObject = getLong(map, key); 661 if (longObject == null) { 662 return 0L; 663 } 664 return longObject.longValue(); 665 } 666 667 /** 668 * Gets a float from a Map in a null-safe manner. 669 * <p> 670 * The float is obtained from the results of {@link #getNumber(Map,Object)}. 671 * 672 * @param <K> the key type 673 * @param map the map to use 674 * @param key the key to look up 675 * @return the value in the Map as a float, <code>0.0F</code> if null map input 676 */ 677 public static <K> float getFloatValue(final Map<? super K, ?> map, final K key) { 678 final Float floatObject = getFloat(map, key); 679 if (floatObject == null) { 680 return 0f; 681 } 682 return floatObject.floatValue(); 683 } 684 685 /** 686 * Gets a double from a Map in a null-safe manner. 687 * <p> 688 * The double is obtained from the results of {@link #getNumber(Map,Object)}. 689 * 690 * @param <K> the key type 691 * @param map the map to use 692 * @param key the key to look up 693 * @return the value in the Map as a double, <code>0.0</code> if null map input 694 */ 695 public static <K> double getDoubleValue(final Map<? super K, ?> map, final K key) { 696 final Double doubleObject = getDouble(map, key); 697 if (doubleObject == null) { 698 return 0d; 699 } 700 return doubleObject.doubleValue(); 701 } 702 703 // Type safe primitive getters with default values 704 //------------------------------------------------------------------------- 705 /** 706 * Gets a boolean from a Map in a null-safe manner, 707 * using the default value if the the conversion fails. 708 * <p> 709 * If the value is a <code>Boolean</code> its value is returned. 710 * If the value is a <code>String</code> and it equals 'true' ignoring case 711 * then <code>true</code> is returned, otherwise <code>false</code>. 712 * If the value is a <code>Number</code> an integer zero value returns 713 * <code>false</code> and non-zero returns <code>true</code>. 714 * Otherwise, <code>defaultValue</code> is returned. 715 * 716 * @param <K> the key type 717 * @param map the map to use 718 * @param key the key to look up 719 * @param defaultValue return if the value is null or if the conversion fails 720 * @return the value in the Map as a Boolean, <code>defaultValue</code> if null map input 721 */ 722 public static <K> boolean getBooleanValue(final Map<? super K, ?> map, final K key, final boolean defaultValue) { 723 final Boolean booleanObject = getBoolean(map, key); 724 if (booleanObject == null) { 725 return defaultValue; 726 } 727 return booleanObject.booleanValue(); 728 } 729 730 /** 731 * Gets a byte from a Map in a null-safe manner, 732 * using the default value if the the conversion fails. 733 * <p> 734 * The byte is obtained from the results of {@link #getNumber(Map,Object)}. 735 * 736 * @param <K> the key type 737 * @param map the map to use 738 * @param key the key to look up 739 * @param defaultValue return if the value is null or if the conversion fails 740 * @return the value in the Map as a byte, <code>defaultValue</code> if null map input 741 */ 742 public static <K> byte getByteValue(final Map<? super K, ?> map, final K key, final byte defaultValue) { 743 final Byte byteObject = getByte(map, key); 744 if (byteObject == null) { 745 return defaultValue; 746 } 747 return byteObject.byteValue(); 748 } 749 750 /** 751 * Gets a short from a Map in a null-safe manner, 752 * using the default value if the the conversion fails. 753 * <p> 754 * The short is obtained from the results of {@link #getNumber(Map,Object)}. 755 * 756 * @param <K> the key type 757 * @param map the map to use 758 * @param key the key to look up 759 * @param defaultValue return if the value is null or if the conversion fails 760 * @return the value in the Map as a short, <code>defaultValue</code> if null map input 761 */ 762 public static <K> short getShortValue(final Map<? super K, ?> map, final K key, final short defaultValue) { 763 final Short shortObject = getShort(map, key); 764 if (shortObject == null) { 765 return defaultValue; 766 } 767 return shortObject.shortValue(); 768 } 769 770 /** 771 * Gets an int from a Map in a null-safe manner, 772 * using the default value if the the conversion fails. 773 * <p> 774 * The int is obtained from the results of {@link #getNumber(Map,Object)}. 775 * 776 * @param <K> the key type 777 * @param map the map to use 778 * @param key the key to look up 779 * @param defaultValue return if the value is null or if the conversion fails 780 * @return the value in the Map as an int, <code>defaultValue</code> if null map input 781 */ 782 public static <K> int getIntValue(final Map<? super K, ?> map, final K key, final int defaultValue) { 783 final Integer integerObject = getInteger(map, key); 784 if (integerObject == null) { 785 return defaultValue; 786 } 787 return integerObject.intValue(); 788 } 789 790 /** 791 * Gets a long from a Map in a null-safe manner, 792 * using the default value if the the conversion fails. 793 * <p> 794 * The long is obtained from the results of {@link #getNumber(Map,Object)}. 795 * 796 * @param <K> the key type 797 * @param map the map to use 798 * @param key the key to look up 799 * @param defaultValue return if the value is null or if the conversion fails 800 * @return the value in the Map as a long, <code>defaultValue</code> if null map input 801 */ 802 public static <K> long getLongValue(final Map<? super K, ?> map, final K key, final long defaultValue) { 803 final Long longObject = getLong(map, key); 804 if (longObject == null) { 805 return defaultValue; 806 } 807 return longObject.longValue(); 808 } 809 810 /** 811 * Gets a float from a Map in a null-safe manner, 812 * using the default value if the the conversion fails. 813 * <p> 814 * The float is obtained from the results of {@link #getNumber(Map,Object)}. 815 * 816 * @param <K> the key type 817 * @param map the map to use 818 * @param key the key to look up 819 * @param defaultValue return if the value is null or if the conversion fails 820 * @return the value in the Map as a float, <code>defaultValue</code> if null map input 821 */ 822 public static <K> float getFloatValue(final Map<? super K, ?> map, final K key, final float defaultValue) { 823 final Float floatObject = getFloat(map, key); 824 if (floatObject == null) { 825 return defaultValue; 826 } 827 return floatObject.floatValue(); 828 } 829 830 /** 831 * Gets a double from a Map in a null-safe manner, 832 * using the default value if the the conversion fails. 833 * <p> 834 * The double is obtained from the results of {@link #getNumber(Map,Object)}. 835 * 836 * @param <K> the key type 837 * @param map the map to use 838 * @param key the key to look up 839 * @param defaultValue return if the value is null or if the conversion fails 840 * @return the value in the Map as a double, <code>defaultValue</code> if null map input 841 */ 842 public static <K> double getDoubleValue(final Map<? super K, ?> map, final K key, final double defaultValue) { 843 final Double doubleObject = getDouble(map, key); 844 if (doubleObject == null) { 845 return defaultValue; 846 } 847 return doubleObject.doubleValue(); 848 } 849 850 // Conversion methods 851 //------------------------------------------------------------------------- 852 /** 853 * Gets a new Properties object initialised with the values from a Map. 854 * A null input will return an empty properties object. 855 * 856 * @param <K> the key type 857 * @param <V> the value type 858 * @param map the map to convert to a Properties object 859 * @return the properties object 860 */ 861 public static <K, V> Properties toProperties(final Map<K, V> map) { 862 final Properties answer = new Properties(); 863 if (map != null) { 864 for (final Entry<K, V> entry2 : map.entrySet()) { 865 final Map.Entry<?, ?> entry = entry2; 866 final Object key = entry.getKey(); 867 final Object value = entry.getValue(); 868 answer.put(key, value); 869 } 870 } 871 return answer; 872 } 873 874 /** 875 * Creates a new HashMap using data copied from a ResourceBundle. 876 * 877 * @param resourceBundle the resource bundle to convert, may not be null 878 * @return the hashmap containing the data 879 * @throws NullPointerException if the bundle is null 880 */ 881 public static Map<String, Object> toMap(final ResourceBundle resourceBundle) { 882 final Enumeration<String> enumeration = resourceBundle.getKeys(); 883 final Map<String, Object> map = new HashMap<String, Object>(); 884 885 while (enumeration.hasMoreElements()) { 886 final String key = enumeration.nextElement(); 887 final Object value = resourceBundle.getObject(key); 888 map.put(key, value); 889 } 890 891 return map; 892 } 893 894 // Printing methods 895 //------------------------------------------------------------------------- 896 /** 897 * Prints the given map with nice line breaks. 898 * <p> 899 * This method prints a nicely formatted String describing the Map. 900 * Each map entry will be printed with key and value. 901 * When the value is a Map, recursive behaviour occurs. 902 * <p> 903 * This method is NOT thread-safe in any special way. You must manually 904 * synchronize on either this class or the stream as required. 905 * 906 * @param out the stream to print to, must not be null 907 * @param label The label to be used, may be <code>null</code>. 908 * If <code>null</code>, the label is not output. 909 * It typically represents the name of the property in a bean or similar. 910 * @param map The map to print, may be <code>null</code>. 911 * If <code>null</code>, the text 'null' is output. 912 * @throws NullPointerException if the stream is <code>null</code> 913 */ 914 @SuppressWarnings("deprecation") 915 public static void verbosePrint(final PrintStream out, final Object label, final Map<?, ?> map) { 916 verbosePrintInternal(out, label, map, new ArrayStack<Map<?, ?>>(), false); 917 } 918 919 /** 920 * Prints the given map with nice line breaks. 921 * <p> 922 * This method prints a nicely formatted String describing the Map. 923 * Each map entry will be printed with key, value and value classname. 924 * When the value is a Map, recursive behaviour occurs. 925 * <p> 926 * This method is NOT thread-safe in any special way. You must manually 927 * synchronize on either this class or the stream as required. 928 * 929 * @param out the stream to print to, must not be null 930 * @param label The label to be used, may be <code>null</code>. 931 * If <code>null</code>, the label is not output. 932 * It typically represents the name of the property in a bean or similar. 933 * @param map The map to print, may be <code>null</code>. 934 * If <code>null</code>, the text 'null' is output. 935 * @throws NullPointerException if the stream is <code>null</code> 936 */ 937 @SuppressWarnings("deprecation") 938 public static void debugPrint(final PrintStream out, final Object label, final Map<?, ?> map) { 939 verbosePrintInternal(out, label, map, new ArrayStack<Map<?, ?>>(), true); 940 } 941 942 // Implementation methods 943 //------------------------------------------------------------------------- 944 /** 945 * Implementation providing functionality for {@link #debugPrint} and for 946 * {@link #verbosePrint}. This prints the given map with nice line breaks. 947 * If the debug flag is true, it additionally prints the type of the object 948 * value. If the contents of a map include the map itself, then the text 949 * <em>(this Map)</em> is printed out. If the contents include a 950 * parent container of the map, the the text <em>(ancestor[i] Map)</em> is 951 * printed, where i actually indicates the number of levels which must be 952 * traversed in the sequential list of ancestors (e.g. father, grandfather, 953 * great-grandfather, etc). 954 * 955 * @param out the stream to print to 956 * @param label the label to be used, may be <code>null</code>. 957 * If <code>null</code>, the label is not output. 958 * It typically represents the name of the property in a bean or similar. 959 * @param map the map to print, may be <code>null</code>. 960 * If <code>null</code>, the text 'null' is output 961 * @param lineage a stack consisting of any maps in which the previous 962 * argument is contained. This is checked to avoid infinite recursion when 963 * printing the output 964 * @param debug flag indicating whether type names should be output. 965 * @throws NullPointerException if the stream is <code>null</code> 966 */ 967 @SuppressWarnings("deprecation") 968 private static void verbosePrintInternal(final PrintStream out, final Object label, final Map<?, ?> map, 969 final ArrayStack<Map<?, ?>> lineage, final boolean debug) { 970 printIndent(out, lineage.size()); 971 972 if (map == null) { 973 if (label != null) { 974 out.print(label); 975 out.print(" = "); 976 } 977 out.println("null"); 978 return; 979 } 980 if (label != null) { 981 out.print(label); 982 out.println(" = "); 983 } 984 985 printIndent(out, lineage.size()); 986 out.println("{"); 987 988 lineage.push(map); 989 990 for (final Map.Entry<?, ?> entry : map.entrySet()) { 991 final Object childKey = entry.getKey(); 992 final Object childValue = entry.getValue(); 993 if (childValue instanceof Map && !lineage.contains(childValue)) { 994 verbosePrintInternal( 995 out, 996 childKey == null ? "null" : childKey, 997 (Map<?, ?>) childValue, 998 lineage, 999 debug); 1000 } else { 1001 printIndent(out, lineage.size()); 1002 out.print(childKey); 1003 out.print(" = "); 1004 1005 final int lineageIndex = lineage.indexOf(childValue); 1006 if (lineageIndex == -1) { 1007 out.print(childValue); 1008 } else if (lineage.size() - 1 == lineageIndex) { 1009 out.print("(this Map)"); 1010 } else { 1011 out.print( 1012 "(ancestor[" 1013 + (lineage.size() - 1 - lineageIndex - 1) 1014 + "] Map)"); 1015 } 1016 1017 if (debug && childValue != null) { 1018 out.print(' '); 1019 out.println(childValue.getClass().getName()); 1020 } else { 1021 out.println(); 1022 } 1023 } 1024 } 1025 1026 lineage.pop(); 1027 1028 printIndent(out, lineage.size()); 1029 out.println(debug ? "} " + map.getClass().getName() : "}"); 1030 } 1031 1032 /** 1033 * Writes indentation to the given stream. 1034 * 1035 * @param out the stream to indent 1036 */ 1037 private static void printIndent(final PrintStream out, final int indent) { 1038 for (int i = 0; i < indent; i++) { 1039 out.print(INDENT_STRING); 1040 } 1041 } 1042 1043 // Misc 1044 //----------------------------------------------------------------------- 1045 /** 1046 * Inverts the supplied map returning a new HashMap such that the keys of 1047 * the input are swapped with the values. 1048 * <p> 1049 * This operation assumes that the inverse mapping is well defined. 1050 * If the input map had multiple entries with the same value mapped to 1051 * different keys, the returned map will map one of those keys to the 1052 * value, but the exact key which will be mapped is undefined. 1053 * 1054 * @param <K> the key type 1055 * @param <V> the value type 1056 * @param map the map to invert, may not be null 1057 * @return a new HashMap containing the inverted data 1058 * @throws NullPointerException if the map is null 1059 */ 1060 public static <K, V> Map<V, K> invertMap(final Map<K, V> map) { 1061 final Map<V, K> out = new HashMap<V, K>(map.size()); 1062 for (final Entry<K, V> entry : map.entrySet()) { 1063 out.put(entry.getValue(), entry.getKey()); 1064 } 1065 return out; 1066 } 1067 1068 //----------------------------------------------------------------------- 1069 /** 1070 * Protects against adding null values to a map. 1071 * <p> 1072 * This method checks the value being added to the map, and if it is null 1073 * it is replaced by an empty string. 1074 * <p> 1075 * This could be useful if the map does not accept null values, or for 1076 * receiving data from a source that may provide null or empty string 1077 * which should be held in the same way in the map. 1078 * <p> 1079 * Keys are not validated. 1080 * Note that this method can be used to circumvent the map's 1081 * value type at runtime. 1082 * 1083 * @param <K> the key type 1084 * @param map the map to add to, may not be null 1085 * @param key the key 1086 * @param value the value, null converted to "" 1087 * @throws NullPointerException if the map is null 1088 */ 1089 public static <K> void safeAddToMap(final Map<? super K, Object> map, final K key, final Object value) 1090 throws NullPointerException { 1091 map.put(key, value == null ? "" : value); 1092 } 1093 1094 //----------------------------------------------------------------------- 1095 /** 1096 * Puts all the keys and values from the specified array into the map. 1097 * <p> 1098 * This method is an alternative to the {@link java.util.Map#putAll(java.util.Map)} 1099 * method and constructors. It allows you to build a map from an object array 1100 * of various possible styles. 1101 * <p> 1102 * If the first entry in the object array implements {@link java.util.Map.Entry} 1103 * or {@link KeyValue} then the key and value are added from that object. 1104 * If the first entry in the object array is an object array itself, then 1105 * it is assumed that index 0 in the sub-array is the key and index 1 is the value. 1106 * Otherwise, the array is treated as keys and values in alternate indices. 1107 * <p> 1108 * For example, to create a color map: 1109 * <pre> 1110 * Map colorMap = MapUtils.putAll(new HashMap(), new String[][] { 1111 * {"RED", "#FF0000"}, 1112 * {"GREEN", "#00FF00"}, 1113 * {"BLUE", "#0000FF"} 1114 * }); 1115 * </pre> 1116 * or: 1117 * <pre> 1118 * Map colorMap = MapUtils.putAll(new HashMap(), new String[] { 1119 * "RED", "#FF0000", 1120 * "GREEN", "#00FF00", 1121 * "BLUE", "#0000FF" 1122 * }); 1123 * </pre> 1124 * or: 1125 * <pre> 1126 * Map colorMap = MapUtils.putAll(new HashMap(), new Map.Entry[] { 1127 * new DefaultMapEntry("RED", "#FF0000"), 1128 * new DefaultMapEntry("GREEN", "#00FF00"), 1129 * new DefaultMapEntry("BLUE", "#0000FF") 1130 * }); 1131 * </pre> 1132 * 1133 * @param <K> the key type 1134 * @param <V> the value type 1135 * @param map the map to populate, must not be null 1136 * @param array an array to populate from, null ignored 1137 * @return the input map 1138 * @throws NullPointerException if map is null 1139 * @throws IllegalArgumentException if sub-array or entry matching used and an entry is invalid 1140 * @throws ClassCastException if the array contents is mixed 1141 * @since 3.2 1142 */ 1143 @SuppressWarnings("unchecked") // As per Javadoc throws CCE for invalid array contents 1144 public static <K, V> Map<K, V> putAll(final Map<K, V> map, final Object[] array) { 1145 map.size(); // force NPE 1146 if (array == null || array.length == 0) { 1147 return map; 1148 } 1149 final Object obj = array[0]; 1150 if (obj instanceof Map.Entry) { 1151 for (final Object element : array) { 1152 // cast ok here, type is checked above 1153 final Map.Entry<K, V> entry = (Map.Entry<K, V>) element; 1154 map.put(entry.getKey(), entry.getValue()); 1155 } 1156 } else if (obj instanceof KeyValue) { 1157 for (final Object element : array) { 1158 // cast ok here, type is checked above 1159 final KeyValue<K, V> keyval = (KeyValue<K, V>) element; 1160 map.put(keyval.getKey(), keyval.getValue()); 1161 } 1162 } else if (obj instanceof Object[]) { 1163 for (int i = 0; i < array.length; i++) { 1164 final Object[] sub = (Object[]) array[i]; 1165 if (sub == null || sub.length < 2) { 1166 throw new IllegalArgumentException("Invalid array element: " + i); 1167 } 1168 // these casts can fail if array has incorrect types 1169 map.put((K) sub[0], (V) sub[1]); 1170 } 1171 } else { 1172 for (int i = 0; i < array.length - 1;) { 1173 // these casts can fail if array has incorrect types 1174 map.put((K) array[i++], (V) array[i++]); 1175 } 1176 } 1177 return map; 1178 } 1179 1180 //----------------------------------------------------------------------- 1181 1182 /** 1183 * Returns an immutable empty map if the argument is <code>null</code>, 1184 * or the argument itself otherwise. 1185 * 1186 * @param <K> the key type 1187 * @param <V> the value type 1188 * @param map the map, possibly <code>null</code> 1189 * @return an empty map if the argument is <code>null</code> 1190 */ 1191 public static <K,V> Map<K,V> emptyIfNull(final Map<K,V> map) { 1192 return map == null ? Collections.<K,V>emptyMap() : map; 1193 } 1194 1195 /** 1196 * Null-safe check if the specified map is empty. 1197 * <p> 1198 * Null returns true. 1199 * 1200 * @param map the map to check, may be null 1201 * @return true if empty or null 1202 * @since 3.2 1203 */ 1204 public static boolean isEmpty(final Map<?,?> map) { 1205 return map == null || map.isEmpty(); 1206 } 1207 1208 /** 1209 * Null-safe check if the specified map is not empty. 1210 * <p> 1211 * Null returns false. 1212 * 1213 * @param map the map to check, may be null 1214 * @return true if non-null and non-empty 1215 * @since 3.2 1216 */ 1217 public static boolean isNotEmpty(final Map<?,?> map) { 1218 return !MapUtils.isEmpty(map); 1219 } 1220 1221 // Map decorators 1222 //----------------------------------------------------------------------- 1223 /** 1224 * Returns a synchronized map backed by the given map. 1225 * <p> 1226 * You must manually synchronize on the returned buffer's iterator to 1227 * avoid non-deterministic behavior: 1228 * 1229 * <pre> 1230 * Map m = MapUtils.synchronizedMap(myMap); 1231 * Set s = m.keySet(); // outside synchronized block 1232 * synchronized (m) { // synchronized on MAP! 1233 * Iterator i = s.iterator(); 1234 * while (i.hasNext()) { 1235 * process (i.next()); 1236 * } 1237 * } 1238 * </pre> 1239 * 1240 * This method uses the implementation in {@link java.util.Collections Collections}. 1241 * 1242 * @param <K> the key type 1243 * @param <V> the value type 1244 * @param map the map to synchronize, must not be null 1245 * @return a synchronized map backed by the given map 1246 */ 1247 public static <K, V> Map<K, V> synchronizedMap(final Map<K, V> map) { 1248 return Collections.synchronizedMap(map); 1249 } 1250 1251 /** 1252 * Returns an unmodifiable map backed by the given map. 1253 * <p> 1254 * This method uses the implementation in the decorators subpackage. 1255 * 1256 * @param <K> the key type 1257 * @param <V> the value type 1258 * @param map the map to make unmodifiable, must not be null 1259 * @return an unmodifiable map backed by the given map 1260 * @throws IllegalArgumentException if the map is null 1261 */ 1262 public static <K, V> Map<K, V> unmodifiableMap(final Map<? extends K, ? extends V> map) { 1263 return UnmodifiableMap.unmodifiableMap(map); 1264 } 1265 1266 /** 1267 * Returns a predicated (validating) map backed by the given map. 1268 * <p> 1269 * Only objects that pass the tests in the given predicates can be added to the map. 1270 * Trying to add an invalid object results in an IllegalArgumentException. 1271 * Keys must pass the key predicate, values must pass the value predicate. 1272 * It is important not to use the original map after invoking this method, 1273 * as it is a backdoor for adding invalid objects. 1274 * 1275 * @param <K> the key type 1276 * @param <V> the value type 1277 * @param map the map to predicate, must not be null 1278 * @param keyPred the predicate for keys, null means no check 1279 * @param valuePred the predicate for values, null means no check 1280 * @return a predicated map backed by the given map 1281 * @throws IllegalArgumentException if the Map is null 1282 */ 1283 public static <K, V> IterableMap<K, V> predicatedMap(final Map<K, V> map, final Predicate<? super K> keyPred, 1284 final Predicate<? super V> valuePred) { 1285 return PredicatedMap.predicatedMap(map, keyPred, valuePred); 1286 } 1287 1288 /** 1289 * Returns a transformed map backed by the given map. 1290 * <p> 1291 * This method returns a new map (decorating the specified map) that 1292 * will transform any new entries added to it. 1293 * Existing entries in the specified map will not be transformed. 1294 * If you want that behaviour, see {@link TransformedMap#transformedMap}. 1295 * <p> 1296 * Each object is passed through the transformers as it is added to the 1297 * Map. It is important not to use the original map after invoking this 1298 * method, as it is a backdoor for adding untransformed objects. 1299 * <p> 1300 * If there are any elements already in the map being decorated, they 1301 * are NOT transformed. 1302 * 1303 * @param <K> the key type 1304 * @param <V> the value type 1305 * @param map the map to transform, must not be null, typically empty 1306 * @param keyTransformer the transformer for the map keys, null means no transformation 1307 * @param valueTransformer the transformer for the map values, null means no transformation 1308 * @return a transformed map backed by the given map 1309 * @throws IllegalArgumentException if the Map is null 1310 */ 1311 public static <K, V> IterableMap<K, V> transformedMap(final Map<K, V> map, 1312 final Transformer<? super K, ? extends K> keyTransformer, 1313 final Transformer<? super V, ? extends V> valueTransformer) { 1314 return TransformedMap.transformingMap(map, keyTransformer, valueTransformer); 1315 } 1316 1317 /** 1318 * Returns a fixed-sized map backed by the given map. 1319 * Elements may not be added or removed from the returned map, but 1320 * existing elements can be changed (for instance, via the 1321 * {@link Map#put(Object,Object)} method). 1322 * 1323 * @param <K> the key type 1324 * @param <V> the value type 1325 * @param map the map whose size to fix, must not be null 1326 * @return a fixed-size map backed by that map 1327 * @throws IllegalArgumentException if the Map is null 1328 */ 1329 public static <K, V> IterableMap<K, V> fixedSizeMap(final Map<K, V> map) { 1330 return FixedSizeMap.fixedSizeMap(map); 1331 } 1332 1333 /** 1334 * Returns a "lazy" map whose values will be created on demand. 1335 * <p> 1336 * When the key passed to the returned map's {@link Map#get(Object)} 1337 * method is not present in the map, then the factory will be used 1338 * to create a new object and that object will become the value 1339 * associated with that key. 1340 * <p> 1341 * For instance: 1342 * <pre> 1343 * Factory factory = new Factory() { 1344 * public Object create() { 1345 * return new Date(); 1346 * } 1347 * } 1348 * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory); 1349 * Object obj = lazyMap.get("test"); 1350 * </pre> 1351 * 1352 * After the above code is executed, <code>obj</code> will contain 1353 * a new <code>Date</code> instance. Furthermore, that <code>Date</code> 1354 * instance is the value for the <code>"test"</code> key in the map. 1355 * 1356 * @param <K> the key type 1357 * @param <V> the value type 1358 * @param map the map to make lazy, must not be null 1359 * @param factory the factory for creating new objects, must not be null 1360 * @return a lazy map backed by the given map 1361 * @throws IllegalArgumentException if the Map or Factory is null 1362 */ 1363 public static <K, V> IterableMap<K, V> lazyMap(final Map<K, V> map, final Factory<? extends V> factory) { 1364 return LazyMap.lazyMap(map, factory); 1365 } 1366 1367 /** 1368 * Returns a "lazy" map whose values will be created on demand. 1369 * <p> 1370 * When the key passed to the returned map's {@link Map#get(Object)} 1371 * method is not present in the map, then the factory will be used 1372 * to create a new object and that object will become the value 1373 * associated with that key. The factory is a {@link Transformer} 1374 * that will be passed the key which it must transform into the value. 1375 * <p> 1376 * For instance: 1377 * <pre> 1378 * Transformer factory = new Transformer() { 1379 * public Object transform(Object mapKey) { 1380 * return new File(mapKey); 1381 * } 1382 * } 1383 * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory); 1384 * Object obj = lazyMap.get("C:/dev"); 1385 * </pre> 1386 * 1387 * After the above code is executed, <code>obj</code> will contain 1388 * a new <code>File</code> instance for the C drive dev directory. 1389 * Furthermore, that <code>File</code> instance is the value for the 1390 * <code>"C:/dev"</code> key in the map. 1391 * <p> 1392 * If a lazy map is wrapped by a synchronized map, the result is a simple 1393 * synchronized cache. When an object is not is the cache, the cache itself 1394 * calls back to the factory Transformer to populate itself, all within the 1395 * same synchronized block. 1396 * 1397 * @param <K> the key type 1398 * @param <V> the value type 1399 * @param map the map to make lazy, must not be null 1400 * @param transformerFactory the factory for creating new objects, must not be null 1401 * @return a lazy map backed by the given map 1402 * @throws IllegalArgumentException if the Map or Transformer is null 1403 */ 1404 public static <K, V> IterableMap<K, V> lazyMap(final Map<K, V> map, 1405 final Transformer<? super K, ? extends V> transformerFactory) { 1406 return LazyMap.lazyMap(map, transformerFactory); 1407 } 1408 1409 /** 1410 * Returns a map that maintains the order of keys that are added 1411 * backed by the given map. 1412 * <p> 1413 * If a key is added twice, the order is determined by the first add. 1414 * The order is observed through the keySet, values and entrySet. 1415 * 1416 * @param <K> the key type 1417 * @param <V> the value type 1418 * @param map the map to order, must not be null 1419 * @return an ordered map backed by the given map 1420 * @throws IllegalArgumentException if the Map is null 1421 */ 1422 public static <K, V> OrderedMap<K, V> orderedMap(final Map<K, V> map) { 1423 return ListOrderedMap.listOrderedMap(map); 1424 } 1425 1426 /** 1427 * Creates a mult-value map backed by the given map which returns 1428 * collections of type ArrayList. 1429 * 1430 * @param <K> the key type 1431 * @param <V> the value type 1432 * @param map the map to decorate 1433 * @return a multi-value map backed by the given map which returns ArrayLists of values. 1434 * @see MultiValueMap 1435 * @since 3.2 1436 */ 1437 public static <K, V> MultiValueMap<K, V> multiValueMap(final Map<K, ? super Collection<V>> map) { 1438 return MultiValueMap.<K, V>multiValueMap(map); 1439 } 1440 1441 /** 1442 * Creates a multi-value map backed by the given map which returns 1443 * collections of the specified type. 1444 * 1445 * @param <K> the key type 1446 * @param <V> the value type 1447 * @param <C> the collection class type 1448 * @param map the map to decorate 1449 * @param collectionClass the type of collections to return from the map (must contain public no-arg constructor 1450 * and extend Collection). 1451 * @return a multi-value map backed by the given map which returns collections of the specified type 1452 * @see MultiValueMap 1453 * @since 3.2 1454 */ 1455 public static <K, V, C extends Collection<V>> MultiValueMap<K, V> multiValueMap(final Map<K, C> map, 1456 final Class<C> collectionClass) { 1457 return MultiValueMap.multiValueMap(map, collectionClass); 1458 } 1459 1460 /** 1461 * Creates a multi-value map backed by the given map which returns 1462 * collections created by the specified collection factory. 1463 * 1464 * @param <K> the key type 1465 * @param <V> the value type 1466 * @param <C> the collection class type 1467 * @param map the map to decorate 1468 * @param collectionFactory a factor which creates collection objects 1469 * @return a multi-value map backed by the given map which returns collections 1470 * created by the specified collection factory 1471 * @see MultiValueMap 1472 * @since 3.2 1473 */ 1474 public static <K, V, C extends Collection<V>> MultiValueMap<K, V> multiValueMap(final Map<K, C> map, 1475 final Factory<C> collectionFactory) { 1476 return MultiValueMap.multiValueMap(map, collectionFactory); 1477 } 1478 1479 // SortedMap decorators 1480 //----------------------------------------------------------------------- 1481 /** 1482 * Returns a synchronized sorted map backed by the given sorted map. 1483 * <p> 1484 * You must manually synchronize on the returned buffer's iterator to 1485 * avoid non-deterministic behavior: 1486 * 1487 * <pre> 1488 * Map m = MapUtils.synchronizedSortedMap(myMap); 1489 * Set s = m.keySet(); // outside synchronized block 1490 * synchronized (m) { // synchronized on MAP! 1491 * Iterator i = s.iterator(); 1492 * while (i.hasNext()) { 1493 * process (i.next()); 1494 * } 1495 * } 1496 * </pre> 1497 * 1498 * This method uses the implementation in {@link java.util.Collections Collections}. 1499 * 1500 * @param <K> the key type 1501 * @param <V> the value type 1502 * @param map the map to synchronize, must not be null 1503 * @return a synchronized map backed by the given map 1504 * @throws IllegalArgumentException if the map is null 1505 */ 1506 public static <K, V> SortedMap<K, V> synchronizedSortedMap(final SortedMap<K, V> map) { 1507 return Collections.synchronizedSortedMap(map); 1508 } 1509 1510 /** 1511 * Returns an unmodifiable sorted map backed by the given sorted map. 1512 * <p> 1513 * This method uses the implementation in the decorators subpackage. 1514 * 1515 * @param <K> the key type 1516 * @param <V> the value type 1517 * @param map the sorted map to make unmodifiable, must not be null 1518 * @return an unmodifiable map backed by the given map 1519 * @throws IllegalArgumentException if the map is null 1520 */ 1521 public static <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> map) { 1522 return UnmodifiableSortedMap.unmodifiableSortedMap(map); 1523 } 1524 1525 /** 1526 * Returns a predicated (validating) sorted map backed by the given map. 1527 * <p> 1528 * Only objects that pass the tests in the given predicates can be added to the map. 1529 * Trying to add an invalid object results in an IllegalArgumentException. 1530 * Keys must pass the key predicate, values must pass the value predicate. 1531 * It is important not to use the original map after invoking this method, 1532 * as it is a backdoor for adding invalid objects. 1533 * 1534 * @param <K> the key type 1535 * @param <V> the value type 1536 * @param map the map to predicate, must not be null 1537 * @param keyPred the predicate for keys, null means no check 1538 * @param valuePred the predicate for values, null means no check 1539 * @return a predicated map backed by the given map 1540 * @throws IllegalArgumentException if the SortedMap is null 1541 */ 1542 public static <K, V> SortedMap<K, V> predicatedSortedMap(final SortedMap<K, V> map, 1543 final Predicate<? super K> keyPred, final Predicate<? super V> valuePred) { 1544 return PredicatedSortedMap.predicatedSortedMap(map, keyPred, valuePred); 1545 } 1546 1547 /** 1548 * Returns a transformed sorted map backed by the given map. 1549 * <p> 1550 * This method returns a new sorted map (decorating the specified map) that 1551 * will transform any new entries added to it. 1552 * Existing entries in the specified map will not be transformed. 1553 * If you want that behaviour, see {@link TransformedSortedMap#transformedSortedMap}. 1554 * <p> 1555 * Each object is passed through the transformers as it is added to the 1556 * Map. It is important not to use the original map after invoking this 1557 * method, as it is a backdoor for adding untransformed objects. 1558 * <p> 1559 * If there are any elements already in the map being decorated, they 1560 * are NOT transformed. 1561 * 1562 * @param <K> the key type 1563 * @param <V> the value type 1564 * @param map the map to transform, must not be null, typically empty 1565 * @param keyTransformer the transformer for the map keys, null means no transformation 1566 * @param valueTransformer the transformer for the map values, null means no transformation 1567 * @return a transformed map backed by the given map 1568 * @throws IllegalArgumentException if the SortedMap is null 1569 */ 1570 public static <K, V> SortedMap<K, V> transformedSortedMap(final SortedMap<K, V> map, 1571 final Transformer<? super K, ? extends K> keyTransformer, 1572 final Transformer<? super V, ? extends V> valueTransformer) { 1573 return TransformedSortedMap.transformingSortedMap(map, keyTransformer, valueTransformer); 1574 } 1575 1576 /** 1577 * Returns a fixed-sized sorted map backed by the given sorted map. 1578 * Elements may not be added or removed from the returned map, but 1579 * existing elements can be changed (for instance, via the 1580 * {@link Map#put(Object,Object)} method). 1581 * 1582 * @param <K> the key type 1583 * @param <V> the value type 1584 * @param map the map whose size to fix, must not be null 1585 * @return a fixed-size map backed by that map 1586 * @throws IllegalArgumentException if the SortedMap is null 1587 */ 1588 public static <K, V> SortedMap<K, V> fixedSizeSortedMap(final SortedMap<K, V> map) { 1589 return FixedSizeSortedMap.fixedSizeSortedMap(map); 1590 } 1591 1592 /** 1593 * Returns a "lazy" sorted map whose values will be created on demand. 1594 * <p> 1595 * When the key passed to the returned map's {@link Map#get(Object)} 1596 * method is not present in the map, then the factory will be used 1597 * to create a new object and that object will become the value 1598 * associated with that key. 1599 * <p> 1600 * For instance: 1601 * 1602 * <pre> 1603 * Factory factory = new Factory() { 1604 * public Object create() { 1605 * return new Date(); 1606 * } 1607 * } 1608 * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory); 1609 * Object obj = lazy.get("test"); 1610 * </pre> 1611 * 1612 * After the above code is executed, <code>obj</code> will contain 1613 * a new <code>Date</code> instance. Furthermore, that <code>Date</code> 1614 * instance is the value for the <code>"test"</code> key. 1615 * 1616 * @param <K> the key type 1617 * @param <V> the value type 1618 * @param map the map to make lazy, must not be null 1619 * @param factory the factory for creating new objects, must not be null 1620 * @return a lazy map backed by the given map 1621 * @throws IllegalArgumentException if the SortedMap or Factory is null 1622 */ 1623 public static <K, V> SortedMap<K, V> lazySortedMap(final SortedMap<K, V> map, final Factory<? extends V> factory) { 1624 return LazySortedMap.lazySortedMap(map, factory); 1625 } 1626 1627 /** 1628 * Returns a "lazy" sorted map whose values will be created on demand. 1629 * <p> 1630 * When the key passed to the returned map's {@link Map#get(Object)} 1631 * method is not present in the map, then the factory will be used 1632 * to create a new object and that object will become the value 1633 * associated with that key. The factory is a {@link Transformer} 1634 * that will be passed the key which it must transform into the value. 1635 * <p> 1636 * For instance: 1637 * <pre> 1638 * Transformer factory = new Transformer() { 1639 * public Object transform(Object mapKey) { 1640 * return new File(mapKey); 1641 * } 1642 * } 1643 * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory); 1644 * Object obj = lazy.get("C:/dev"); 1645 * </pre> 1646 * 1647 * After the above code is executed, <code>obj</code> will contain 1648 * a new <code>File</code> instance for the C drive dev directory. 1649 * Furthermore, that <code>File</code> instance is the value for the 1650 * <code>"C:/dev"</code> key in the map. 1651 * <p> 1652 * If a lazy map is wrapped by a synchronized map, the result is a simple 1653 * synchronized cache. When an object is not is the cache, the cache itself 1654 * calls back to the factory Transformer to populate itself, all within the 1655 * same synchronized block. 1656 * 1657 * @param <K> the key type 1658 * @param <V> the value type 1659 * @param map the map to make lazy, must not be null 1660 * @param transformerFactory the factory for creating new objects, must not be null 1661 * @return a lazy map backed by the given map 1662 * @throws IllegalArgumentException if the Map or Transformer is null 1663 */ 1664 public static <K, V> SortedMap<K, V> lazySortedMap(final SortedMap<K, V> map, 1665 final Transformer<? super K, ? extends V> transformerFactory) { 1666 return LazySortedMap.lazySortedMap(map, transformerFactory); 1667 } 1668 1669 /** 1670 * Populates a Map using the supplied <code>Transformer</code> to transform the elements 1671 * into keys, using the unaltered element as the value in the <code>Map</code>. 1672 * 1673 * @param <K> the key type 1674 * @param <V> the value type 1675 * @param map the <code>Map</code> to populate. 1676 * @param elements the <code>Iterable</code> containing the input values for the map. 1677 * @param keyTransformer the <code>Transformer</code> used to transform the element into a key value 1678 * @throws NullPointerException if the map, elements or transformer are null 1679 */ 1680 public static <K, V> void populateMap(final Map<K, V> map, final Iterable<? extends V> elements, 1681 final Transformer<V, K> keyTransformer) { 1682 populateMap(map, elements, keyTransformer, TransformerUtils.<V>nopTransformer()); 1683 } 1684 1685 /** 1686 * Populates a Map using the supplied <code>Transformer</code>s to transform the elements 1687 * into keys and values. 1688 * 1689 * @param <K> the key type 1690 * @param <V> the value type 1691 * @param <E> the type of object contained in the {@link Iterable} 1692 * @param map the <code>Map</code> to populate. 1693 * @param elements the <code>Iterable</code> containing the input values for the map. 1694 * @param keyTransformer the <code>Transformer</code> used to transform the element into a key value 1695 * @param valueTransformer the <code>Transformer</code> used to transform the element into a value 1696 * @throws NullPointerException if the map, elements or transformers are null 1697 */ 1698 public static <K, V, E> void populateMap(final Map<K, V> map, final Iterable<? extends E> elements, 1699 final Transformer<E, K> keyTransformer, 1700 final Transformer<E, V> valueTransformer) { 1701 final Iterator<? extends E> iter = elements.iterator(); 1702 while (iter.hasNext()) { 1703 final E temp = iter.next(); 1704 map.put(keyTransformer.transform(temp), valueTransformer.transform(temp)); 1705 } 1706 } 1707 1708 /** 1709 * Populates a MultiMap using the supplied <code>Transformer</code> to transform the elements 1710 * into keys, using the unaltered element as the value in the <code>MultiMap</code>. 1711 * 1712 * @param <K> the key type 1713 * @param <V> the value type 1714 * @param map the <code>MultiMap</code> to populate. 1715 * @param elements the <code>Iterable</code> to use as input values for the map. 1716 * @param keyTransformer the <code>Transformer</code> used to transform the element into a key value 1717 * @throws NullPointerException if the map, elements or transformer are null 1718 */ 1719 public static <K, V> void populateMap(final MultiMap<K, V> map, final Iterable<? extends V> elements, 1720 final Transformer<V, K> keyTransformer) { 1721 populateMap(map, elements, keyTransformer, TransformerUtils.<V>nopTransformer()); 1722 } 1723 1724 /** 1725 * Populates a MultiMap using the supplied <code>Transformer</code>s to transform the elements 1726 * into keys and values. 1727 * 1728 * @param <K> the key type 1729 * @param <V> the value type 1730 * @param <E> the type of object contained in the {@link Iterable} 1731 * @param map the <code>MultiMap</code> to populate. 1732 * @param elements the <code>Iterable</code> containing the input values for the map. 1733 * @param keyTransformer the <code>Transformer</code> used to transform the element into a key value 1734 * @param valueTransformer the <code>Transformer</code> used to transform the element into a value 1735 * @throws NullPointerException if the map, collection or transformers are null 1736 */ 1737 public static <K, V, E> void populateMap(final MultiMap<K, V> map, final Iterable<? extends E> elements, 1738 final Transformer<E, K> keyTransformer, 1739 final Transformer<E, V> valueTransformer) { 1740 final Iterator<? extends E> iter = elements.iterator(); 1741 while (iter.hasNext()) { 1742 final E temp = iter.next(); 1743 map.put(keyTransformer.transform(temp), valueTransformer.transform(temp)); 1744 } 1745 } 1746 1747 /** 1748 * Get the specified {@link Map} as an {@link IterableMap}. 1749 * 1750 * @param <K> the key type 1751 * @param <V> the value type 1752 * @param map to wrap if necessary. 1753 * @return IterableMap<K, V> 1754 * @since 4.0 1755 */ 1756 public static <K, V> IterableMap<K, V> iterableMap(final Map<K, V> map) { 1757 if (map == null) { 1758 throw new IllegalArgumentException("Map must not be null"); 1759 } 1760 return map instanceof IterableMap ? (IterableMap<K, V>) map : new AbstractMapDecorator<K, V>(map) {}; 1761 } 1762 1763 /** 1764 * Get the specified {@link SortedMap} as an {@link IterableSortedMap}. 1765 * 1766 * @param <K> the key type 1767 * @param <V> the value type 1768 * @param sortedMap to wrap if necessary 1769 * @return {@link IterableSortedMap}<K, V> 1770 * @since 4.0 1771 */ 1772 public static <K, V> IterableSortedMap<K, V> iterableSortedMap(final SortedMap<K, V> sortedMap) { 1773 if (sortedMap == null) { 1774 throw new IllegalArgumentException("Map must not be null"); 1775 } 1776 return sortedMap instanceof IterableSortedMap ? (IterableSortedMap<K, V>) sortedMap : 1777 new AbstractSortedMapDecorator<K, V>(sortedMap) {}; 1778 } 1779 1780}