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