    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}