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