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