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