View Javadoc

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