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