All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.collections4.MapUtils Maven / Gradle / Ivy

Go to download

The Apache Commons Collections package contains types that extend and augment the Java Collections Framework.

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.collections4;

import java.io.PrintStream;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.apache.commons.collections4.map.AbstractMapDecorator;
import org.apache.commons.collections4.map.AbstractSortedMapDecorator;
import org.apache.commons.collections4.map.FixedSizeMap;
import org.apache.commons.collections4.map.FixedSizeSortedMap;
import org.apache.commons.collections4.map.LazyMap;
import org.apache.commons.collections4.map.LazySortedMap;
import org.apache.commons.collections4.map.ListOrderedMap;
import org.apache.commons.collections4.map.MultiValueMap;
import org.apache.commons.collections4.map.PredicatedMap;
import org.apache.commons.collections4.map.PredicatedSortedMap;
import org.apache.commons.collections4.map.TransformedMap;
import org.apache.commons.collections4.map.TransformedSortedMap;
import org.apache.commons.collections4.map.UnmodifiableMap;
import org.apache.commons.collections4.map.UnmodifiableSortedMap;

/**
 * Provides utility methods and decorators for {@link Map} and {@link SortedMap} instances.
 * 

* It contains various type safe methods as well as other useful features like deep copying. *

*

* It also provides the following decorators: *

* *
    *
  • {@link #fixedSizeMap(Map)} *
  • {@link #fixedSizeSortedMap(SortedMap)} *
  • {@link #lazyMap(Map,Factory)} *
  • {@link #lazyMap(Map,Transformer)} *
  • {@link #lazySortedMap(SortedMap,Factory)} *
  • {@link #lazySortedMap(SortedMap,Transformer)} *
  • {@link #predicatedMap(Map,Predicate,Predicate)} *
  • {@link #predicatedSortedMap(SortedMap,Predicate,Predicate)} *
  • {@link #transformedMap(Map, Transformer, Transformer)} *
  • {@link #transformedSortedMap(SortedMap, Transformer, Transformer)} *
  • {@link #multiValueMap(Map)} *
  • {@link #multiValueMap(Map, Class)} *
  • {@link #multiValueMap(Map, Factory)} *
* * @since 1.0 */ @SuppressWarnings("deprecation") public class MapUtils { /** * An empty unmodifiable sorted map. This is not provided in the JDK. */ @SuppressWarnings("rawtypes") public static final SortedMap EMPTY_SORTED_MAP = UnmodifiableSortedMap.unmodifiableSortedMap(new TreeMap<>()); /** * String used to indent the verbose and debug Map prints. */ private static final String INDENT_STRING = " "; /** * Applies the {@code getFunction} and returns its result if non-null, if null returns the result of applying the * default function. * * @param The key type. * @param The result type. * @param map The map to query. * @param key The key into the map. * @param getFunction The get function. * @param defaultFunction The function to provide a default value. * @return The result of applying a function. */ private static R applyDefaultFunction(final Map map, final K key, final BiFunction, K, R> getFunction, final Function defaultFunction) { return applyDefaultFunction(map, key, getFunction, defaultFunction, null); } /** * Applies the {@code getFunction} and returns its result if non-null, if null returns the result of applying the * default function. * * @param The key type. * @param The result type. * @param map The map to query. * @param key The key into the map. * @param getFunction The get function. * @param defaultFunction The function to provide a default value. * @param defaultValue The default value. * @return The result of applying a function. */ private static R applyDefaultFunction(final Map map, final K key, final BiFunction, K, R> getFunction, final Function defaultFunction, final R defaultValue) { R value = map != null && getFunction != null ? getFunction.apply(map, key) : null; if (value == null) { value = defaultFunction != null ? defaultFunction.apply(key) : null; } return value != null ? value : defaultValue; } /** * Applies the {@code getFunction} and returns its result if non-null, if null returns the {@code defaultValue}. * * @param The key type. * @param The result type. * @param map The map to query. * @param key The key into the map. * @param getFunction The get function. * @param defaultValue The default value. * @return The result of applying a function. */ private static R applyDefaultValue(final Map map, final K key, final BiFunction, K, R> getFunction, final R defaultValue) { final R value = map != null && getFunction != null ? getFunction.apply(map, key) : null; return value == null ? defaultValue : value; } /** * Prints the given map with nice line breaks. *

* This method prints a nicely formatted String describing the Map. Each map entry will be printed with key, value * and value class name. When the value is a Map, recursive behavior occurs. *

*

* This method is NOT thread-safe in any special way. You must manually synchronize on either this class or the * stream as required. *

* * @param out the stream to print to, must not be null * @param label The label to be used, may be {@code null}. If {@code null}, the label is not output. It * typically represents the name of the property in a bean or similar. * @param map The map to print, may be {@code null}. If {@code null}, the text 'null' is output. * @throws NullPointerException if the stream is {@code null} */ public static void debugPrint(final PrintStream out, final Object label, final Map map) { verbosePrintInternal(out, label, map, new ArrayDeque<>(), true); } /** * Returns an immutable empty map if the argument is {@code null}, or the argument itself otherwise. * * @param the key type * @param the value type * @param map the map, possibly {@code null} * @return an empty map if the argument is {@code null} */ public static Map emptyIfNull(final Map map) { return map == null ? Collections.emptyMap() : map; } /** * Returns a fixed-sized map backed by the given map. Elements may not be added or removed from the returned map, * but existing elements can be changed (for instance, via the {@link Map#put(Object,Object)} method). * * @param the key type * @param the value type * @param map the map whose size to fix, must not be null * @return a fixed-size map backed by that map * @throws NullPointerException if the Map is null */ public static IterableMap fixedSizeMap(final Map map) { return FixedSizeMap.fixedSizeMap(map); } /** * Returns a fixed-sized sorted map backed by the given sorted map. Elements may not be added or removed from the * returned map, but existing elements can be changed (for instance, via the {@link Map#put(Object,Object)} method). * * @param the key type * @param the value type * @param map the map whose size to fix, must not be null * @return a fixed-size map backed by that map * @throws NullPointerException if the SortedMap is null */ public static SortedMap fixedSizeSortedMap(final SortedMap map) { return FixedSizeSortedMap.fixedSizeSortedMap(map); } /** * Gets a Boolean from a Map in a null-safe manner. *

* If the value is a {@code Boolean} it is returned directly. If the value is a {@code String} and it * equals 'true' ignoring case then {@code true} is returned, otherwise {@code false}. If the value is a * {@code Number} an integer zero value returns {@code false} and non-zero returns {@code true}. * Otherwise, {@code null} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Boolean, {@code null} if null map input */ public static Boolean getBoolean(final Map map, final K key) { if (map != null) { final Object answer = map.get(key); if (answer != null) { if (answer instanceof Boolean) { return (Boolean) answer; } if (answer instanceof String) { return Boolean.valueOf((String) answer); } if (answer instanceof Number) { final Number n = (Number) answer; return n.intValue() != 0 ? Boolean.TRUE : Boolean.FALSE; } } } return null; } /** * Looks up the given key in the given map, converting the result into a boolean, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a boolean, or defaultValue if the original value is null, the map is null or the * boolean conversion fails */ public static Boolean getBoolean(final Map map, final K key, final Boolean defaultValue) { return applyDefaultValue(map, key, MapUtils::getBoolean, defaultValue); } /** * Looks up the given key in the given map, converting the result into a boolean, using the defaultFunction to * produce the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a boolean, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the boolean conversion fails * @since 4.5.0-M1 */ public static Boolean getBoolean(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getBoolean, defaultFunction); } /** * Gets a boolean from a Map in a null-safe manner. *

* If the value is a {@code Boolean} its value is returned. If the value is a {@code String} and it equals * 'true' ignoring case then {@code true} is returned, otherwise {@code false}. If the value is a * {@code Number} an integer zero value returns {@code false} and non-zero returns {@code true}. * Otherwise, {@code false} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Boolean, {@code false} if null map input */ public static boolean getBooleanValue(final Map map, final K key) { return Boolean.TRUE.equals(getBoolean(map, key)); } /** * Gets a boolean from a Map in a null-safe manner, using the default value if the conversion fails. *

* If the value is a {@code Boolean} its value is returned. If the value is a {@code String} and it equals * 'true' ignoring case then {@code true} is returned, otherwise {@code false}. If the value is a * {@code Number} an integer zero value returns {@code false} and non-zero returns {@code true}. * Otherwise, {@code defaultValue} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a Boolean, {@code defaultValue} if null map input */ public static boolean getBooleanValue(final Map map, final K key, final boolean defaultValue) { return applyDefaultValue(map, key, MapUtils::getBoolean, defaultValue).booleanValue(); } /** * Gets a boolean from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* If the value is a {@code Boolean} its value is returned. If the value is a {@code String} and it equals * 'true' ignoring case then {@code true} is returned, otherwise {@code false}. If the value is a * {@code Number} an integer zero value returns {@code false} and non-zero returns {@code true}. * Otherwise, defaultValue produced by the {@code defaultFunction} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a Boolean, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static boolean getBooleanValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getBoolean, defaultFunction, false).booleanValue(); } /** * Gets a Byte from a Map in a null-safe manner. *

* The Byte is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Byte, {@code null} if null map input */ public static Byte getByte(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Byte) { return (Byte) answer; } return Byte.valueOf(answer.byteValue()); } /** * Looks up the given key in the given map, converting the result into a byte, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Byte getByte(final Map map, final K key, final Byte defaultValue) { return applyDefaultValue(map, key, MapUtils::getByte, defaultValue); } /** * Looks up the given key in the given map, converting the result into a byte, using the defaultFunction to produce * the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Byte getByte(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getByte, defaultFunction); } /** * Gets a byte from a Map in a null-safe manner. *

* The byte is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a byte, {@code 0} if null map input */ public static byte getByteValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getByte, 0).byteValue(); } /** * Gets a byte from a Map in a null-safe manner, using the default value if the conversion fails. *

* The byte is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a byte, {@code defaultValue} if null map input */ public static byte getByteValue(final Map map, final K key, final byte defaultValue) { return applyDefaultValue(map, key, MapUtils::getByte, defaultValue).byteValue(); } /** * Gets a byte from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The byte is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a byte, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static byte getByteValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getByte, defaultFunction, (byte) 0).byteValue(); } /** * Gets a Double from a Map in a null-safe manner. *

* The Double is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Double, {@code null} if null map input */ public static Double getDouble(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Double) { return (Double) answer; } return Double.valueOf(answer.doubleValue()); } /** * Looks up the given key in the given map, converting the result into a double, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Double getDouble(final Map map, final K key, final Double defaultValue) { return applyDefaultValue(map, key, MapUtils::getDouble, defaultValue); } /** * Looks up the given key in the given map, converting the result into a double, using the defaultFunction to * produce the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Double getDouble(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getDouble, defaultFunction); } /** * Gets a double from a Map in a null-safe manner. *

* The double is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a double, {@code 0.0} if null map input */ public static double getDoubleValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getDouble, 0d).doubleValue(); } /** * Gets a double from a Map in a null-safe manner, using the default value if the conversion fails. *

* The double is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a double, {@code defaultValue} if null map input */ public static double getDoubleValue(final Map map, final K key, final double defaultValue) { return applyDefaultValue(map, key, MapUtils::getDouble, defaultValue).doubleValue(); } /** * Gets a double from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The double is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a double, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static double getDoubleValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getDouble, defaultFunction, 0d).doubleValue(); } /** * Gets a Float from a Map in a null-safe manner. *

* The Float is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Float, {@code null} if null map input */ public static Float getFloat(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Float) { return (Float) answer; } return Float.valueOf(answer.floatValue()); } /** * Looks up the given key in the given map, converting the result into a float, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Float getFloat(final Map map, final K key, final Float defaultValue) { return applyDefaultValue(map, key, MapUtils::getFloat, defaultValue); } /** * Looks up the given key in the given map, converting the result into a float, using the defaultFunction to produce * the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Float getFloat(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getFloat, defaultFunction); } /** * Gets a float from a Map in a null-safe manner. *

* The float is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a float, {@code 0.0F} if null map input */ public static float getFloatValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getFloat, 0f).floatValue(); } /** * Gets a float from a Map in a null-safe manner, using the default value if the conversion fails. *

* The float is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a float, {@code defaultValue} if null map input */ public static float getFloatValue(final Map map, final K key, final float defaultValue) { return applyDefaultValue(map, key, MapUtils::getFloat, defaultValue).floatValue(); } /** * Gets a float from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The float is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a float, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static float getFloatValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getFloat, defaultFunction, 0f).floatValue(); } /** * Gets an Integer from a Map in a null-safe manner. *

* The Integer is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as an Integer, {@code null} if null map input */ public static Integer getInteger(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Integer) { return (Integer) answer; } return Integer.valueOf(answer.intValue()); } /** * Looks up the given key in the given map, converting the result into an integer, using the defaultFunction to * produce the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Integer getInteger(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getInteger, defaultFunction); } /** * Looks up the given key in the given map, converting the result into an integer, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Integer getInteger(final Map map, final K key, final Integer defaultValue) { return applyDefaultValue(map, key, MapUtils::getInteger, defaultValue); } /** * Gets an int from a Map in a null-safe manner. *

* The int is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as an int, {@code 0} if null map input */ public static int getIntValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getInteger, 0).intValue(); } /** * Gets an int from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The int is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as an int, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static int getIntValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getInteger, defaultFunction, 0).byteValue(); } /** * Gets an int from a Map in a null-safe manner, using the default value if the conversion fails. *

* The int is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as an int, {@code defaultValue} if null map input */ public static int getIntValue(final Map map, final K key, final int defaultValue) { return applyDefaultValue(map, key, MapUtils::getInteger, defaultValue).intValue(); } /** * Gets a Long from a Map in a null-safe manner. *

* The Long is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Long, {@code null} if null map input */ public static Long getLong(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Long) { return (Long) answer; } return Long.valueOf(answer.longValue()); } /** * Looks up the given key in the given map, converting the result into a Long, using the defaultFunction to produce * the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Long getLong(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getLong, defaultFunction); } /** * Looks up the given key in the given map, converting the result into a long, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Long getLong(final Map map, final K key, final Long defaultValue) { return applyDefaultValue(map, key, MapUtils::getLong, defaultValue); } /** * Gets a long from a Map in a null-safe manner. *

* The long is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a long, {@code 0L} if null map input */ public static long getLongValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getLong, 0L).longValue(); } /** * Gets a long from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The long is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a long, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static long getLongValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getLong, defaultFunction, 0L).byteValue(); } /** * Gets a long from a Map in a null-safe manner, using the default value if the conversion fails. *

* The long is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a long, {@code defaultValue} if null map input */ public static long getLongValue(final Map map, final K key, final long defaultValue) { return applyDefaultValue(map, key, MapUtils::getLong, defaultValue).longValue(); } /** * Gets a Map from a Map in a null-safe manner. *

* If the value returned from the specified map is not a Map then {@code null} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Map, {@code null} if null map input */ public static Map getMap(final Map map, final K key) { if (map != null) { final Object answer = map.get(key); if (answer instanceof Map) { return (Map) answer; } } return null; } /** * Looks up the given key in the given map, converting the result into a map, using the defaultFunction to produce * the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the map conversion fails * @since 4.5.0-M1 */ public static Map getMap(final Map map, final K key, final Function> defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getMap, defaultFunction); } /** * Looks up the given key in the given map, converting the result into a map, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * map conversion fails */ public static Map getMap(final Map map, final K key, final Map defaultValue) { return applyDefaultValue(map, key, MapUtils::getMap, defaultValue); } /** * Gets a Number from a Map in a null-safe manner. *

* If the value is a {@code Number} it is returned directly. If the value is a {@code String} it is * converted using {@link NumberFormat#parse(String)} on the system default formatter returning {@code null} if * the conversion fails. Otherwise, {@code null} is returned. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Number, {@code null} if null map input */ public static Number getNumber(final Map map, final K key) { if (map != null) { final Object answer = map.get(key); if (answer != null) { if (answer instanceof Number) { return (Number) answer; } if (answer instanceof String) { try { final String text = (String) answer; return NumberFormat.getInstance().parse(text); } catch (final ParseException e) { // NOPMD // failure means null is returned } } } } return null; } /** * Looks up the given key in the given map, converting the result into a number, using the defaultFunction to * produce the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Number getNumber(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getNumber, defaultFunction); } /** * Looks up the given key in the given map, converting the result into a number, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Number getNumber(final Map map, final K key, final Number defaultValue) { return applyDefaultValue(map, key, MapUtils::getNumber, defaultValue); } /** * Gets from a Map in a null-safe manner. * * @param the key type * @param the value type * @param map the map to use * @param key the key to look up * @return the value in the Map, {@code null} if null map input */ public static V getObject(final Map map, final K key) { if (map != null) { return map.get(key); } return null; } /** * Looks up the given key in the given map, converting null into the given default value. * * @param the key type * @param the value type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null * @return the value in the map, or defaultValue if the original value is null or the map is null */ public static V getObject(final Map map, final K key, final V defaultValue) { if (map != null) { final V answer = map.get(key); if (answer != null) { return answer; } } return defaultValue; } /** * Gets a Short from a Map in a null-safe manner. *

* The Short is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a Short, {@code null} if null map input */ public static Short getShort(final Map map, final K key) { final Number answer = getNumber(map, key); if (answer == null) { return null; } if (answer instanceof Short) { return (Short) answer; } return Short.valueOf(answer.shortValue()); } /** * Looks up the given key in the given map, converting the result into a short, using the defaultFunction to produce * the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the number conversion fails * @since 4.5.0-M1 */ public static Short getShort(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getShort, defaultFunction); } /** * Looks up the given key in the given map, converting the result into a short, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a number, or defaultValue if the original value is null, the map is null or the * number conversion fails */ public static Short getShort(final Map map, final K key, final Short defaultValue) { return applyDefaultValue(map, key, MapUtils::getShort, defaultValue); } /** * Gets a short from a Map in a null-safe manner. *

* The short is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a short, {@code 0} if null map input */ public static short getShortValue(final Map map, final K key) { return applyDefaultValue(map, key, MapUtils::getShort, 0).shortValue(); } /** * Gets a short from a Map in a null-safe manner, using the default value produced by the defaultFunction if the * conversion fails. *

* The short is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultFunction produce the default value to return if the value is null or if the conversion fails * @return the value in the Map as a short, default value produced by the {@code defaultFunction} if null map * input * @since 4.5.0-M1 */ public static short getShortValue(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getShort, defaultFunction, (short) 0).shortValue(); } /** * Gets a short from a Map in a null-safe manner, using the default value if the conversion fails. *

* The short is obtained from the results of {@link #getNumber(Map,Object)}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @param defaultValue return if the value is null or if the conversion fails * @return the value in the Map as a short, {@code defaultValue} if null map input */ public static short getShortValue(final Map map, final K key, final short defaultValue) { return applyDefaultValue(map, key, MapUtils::getShort, defaultValue).shortValue(); } /** * Gets a String from a Map in a null-safe manner. *

* The String is obtained via {@code toString}. *

* * @param the key type * @param map the map to use * @param key the key to look up * @return the value in the Map as a String, {@code null} if null map input */ public static String getString(final Map map, final K key) { if (map != null) { final Object answer = map.get(key); if (answer != null) { return answer.toString(); } } return null; } /** * Looks up the given key in the given map, converting the result into a string, using the defaultFunction to * produce the default value if the conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultFunction what to produce the default value if the value is null or if the conversion fails * @return the value in the map as a string, or defaultValue produced by the defaultFunction if the original value * is null, the map is null or the string conversion fails * @since 4.5.0-M1 */ public static String getString(final Map map, final K key, final Function defaultFunction) { return applyDefaultFunction(map, key, MapUtils::getString, defaultFunction); } /** * Looks up the given key in the given map, converting the result into a string, using the default value if the * conversion fails. * * @param the key type * @param map the map whose value to look up * @param key the key of the value to look up in that map * @param defaultValue what to return if the value is null or if the conversion fails * @return the value in the map as a string, or defaultValue if the original value is null, the map is null or the * string conversion fails */ public static String getString(final Map map, final K key, final String defaultValue) { return applyDefaultValue(map, key, MapUtils::getString, defaultValue); } /** * Inverts the supplied map returning a new HashMap such that the keys of the input are swapped with the values. *

* This operation assumes that the inverse mapping is well defined. If the input map had multiple entries with the * same value mapped to different keys, the returned map will map one of those keys to the value, but the exact key * which will be mapped is undefined. *

* * @param the key type * @param the value type * @param map the map to invert, must not be null * @return a new HashMap containing the inverted data * @throws NullPointerException if the map is null */ public static Map invertMap(final Map map) { Objects.requireNonNull(map, "map"); final Map out = new HashMap<>(map.size()); for (final Entry entry : map.entrySet()) { out.put(entry.getValue(), entry.getKey()); } return out; } /** * Null-safe check if the specified map is empty. *

* Null returns true. *

* * @param map the map to check, may be null * @return true if empty or null * @since 3.2 */ public static boolean isEmpty(final Map map) { return map == null || map.isEmpty(); } /** * Null-safe check if the specified map is not empty. *

* Null returns false. *

* * @param map the map to check, may be null * @return true if non-null and non-empty * @since 3.2 */ public static boolean isNotEmpty(final Map map) { return !isEmpty(map); } /** * Gets the specified {@link Map} as an {@link IterableMap}. * * @param the key type * @param the value type * @param map to wrap if necessary. * @return IterableMap<K, V> * @throws NullPointerException if map is null * @since 4.0 */ public static IterableMap iterableMap(final Map map) { Objects.requireNonNull(map, "map"); return map instanceof IterableMap ? (IterableMap) map : new AbstractMapDecorator(map) { // empty }; } /** * Gets the specified {@link SortedMap} as an {@link IterableSortedMap}. * * @param the key type * @param the value type * @param sortedMap to wrap if necessary * @return {@link IterableSortedMap}<K, V> * @throws NullPointerException if sortedMap is null * @since 4.0 */ public static IterableSortedMap iterableSortedMap(final SortedMap sortedMap) { Objects.requireNonNull(sortedMap, "sortedMap"); return sortedMap instanceof IterableSortedMap ? (IterableSortedMap) sortedMap : new AbstractSortedMapDecorator(sortedMap) { // empty }; } /** * Returns a "lazy" map whose values will be created on demand. *

* When the key passed to the returned map's {@link Map#get(Object)} method is not present in the map, then the * factory will be used to create a new object and that object will become the value associated with that key. *

*

* For instance: *

*
     * Factory factory = new Factory() {
     *     public Object create() {
     *         return new Date();
     *     }
     * }
     * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
     * Object obj = lazyMap.get("test");
     * 
*

* After the above code is executed, {@code obj} will contain a new {@code Date} instance. Furthermore, * that {@code Date} instance is the value for the {@code "test"} key in the map. *

* * @param the key type * @param the value type * @param map the map to make lazy, must not be null * @param factory the factory for creating new objects, must not be null * @return a lazy map backed by the given map * @throws NullPointerException if the Map or Factory is null */ public static IterableMap lazyMap(final Map map, final Factory factory) { return LazyMap.lazyMap(map, factory); } /** * Returns a "lazy" map whose values will be created on demand. *

* When the key passed to the returned map's {@link Map#get(Object)} method is not present in the map, then the * factory will be used to create a new object and that object will become the value associated with that key. The * factory is a {@link Transformer} that will be passed the key which it must transform into the value. *

*

* For instance: *

*
     * Transformer factory = new Transformer() {
     *     public Object transform(Object mapKey) {
     *         return new File(mapKey);
     *     }
     * }
     * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
     * Object obj = lazyMap.get("C:/dev");
     * 
* *

* After the above code is executed, {@code obj} will contain a new {@code File} instance for the C drive * dev directory. Furthermore, that {@code File} instance is the value for the {@code "C:/dev"} key in the * map. *

*

* If a lazy map is wrapped by a synchronized map, the result is a simple synchronized cache. When an object is not * is the cache, the cache itself calls back to the factory Transformer to populate itself, all within the same * synchronized block. *

* * @param the key type * @param the value type * @param map the map to make lazy, must not be null * @param transformerFactory the factory for creating new objects, must not be null * @return a lazy map backed by the given map * @throws NullPointerException if the Map or Transformer is null */ public static IterableMap lazyMap(final Map map, final Transformer transformerFactory) { return LazyMap.lazyMap(map, transformerFactory); } /** * Returns a "lazy" sorted map whose values will be created on demand. *

* When the key passed to the returned map's {@link Map#get(Object)} method is not present in the map, then the * factory will be used to create a new object and that object will become the value associated with that key. *

*

* For instance: *

*
     * Factory factory = new Factory() {
     *     public Object create() {
     *         return new Date();
     *     }
     * }
     * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory);
     * Object obj = lazy.get("test");
     * 
*

* After the above code is executed, {@code obj} will contain a new {@code Date} instance. Furthermore, * that {@code Date} instance is the value for the {@code "test"} key. *

* * @param the key type * @param the value type * @param map the map to make lazy, must not be null * @param factory the factory for creating new objects, must not be null * @return a lazy map backed by the given map * @throws NullPointerException if the SortedMap or Factory is null */ public static SortedMap lazySortedMap(final SortedMap map, final Factory factory) { return LazySortedMap.lazySortedMap(map, factory); } /** * Returns a "lazy" sorted map whose values will be created on demand. *

* When the key passed to the returned map's {@link Map#get(Object)} method is not present in the map, then the * factory will be used to create a new object and that object will become the value associated with that key. The * factory is a {@link Transformer} that will be passed the key which it must transform into the value. *

*

* For instance: *

*
     * Transformer factory = new Transformer() {
     *     public Object transform(Object mapKey) {
     *         return new File(mapKey);
     *     }
     * }
     * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory);
     * Object obj = lazy.get("C:/dev");
     * 
*

* After the above code is executed, {@code obj} will contain a new {@code File} instance for the C drive * dev directory. Furthermore, that {@code File} instance is the value for the {@code "C:/dev"} key in the * map. *

*

* If a lazy map is wrapped by a synchronized map, the result is a simple synchronized cache. When an object is not * is the cache, the cache itself calls back to the factory Transformer to populate itself, all within the same * synchronized block. *

* * @param the key type * @param the value type * @param map the map to make lazy, must not be null * @param transformerFactory the factory for creating new objects, must not be null * @return a lazy map backed by the given map * @throws NullPointerException if the Map or Transformer is null */ public static SortedMap lazySortedMap(final SortedMap map, final Transformer transformerFactory) { return LazySortedMap.lazySortedMap(map, transformerFactory); } /** * Creates a multi-value map backed by the given map which returns collections of type ArrayList. * * @param the key type * @param the value type * @param map the map to decorate * @return a multi-value map backed by the given map which returns ArrayLists of values. * @see MultiValueMap * @since 3.2 * @deprecated since 4.1, use {@link MultiValuedMap} instead */ @Deprecated public static MultiValueMap multiValueMap(final Map> map) { return MultiValueMap.multiValueMap(map); } /** * Creates a multi-value map backed by the given map which returns collections of the specified type. * * @param the key type * @param the value type * @param the collection class type * @param map the map to decorate * @param collectionClass the type of collections to return from the map (must contain public no-arg constructor and * extend Collection) * @return a multi-value map backed by the given map which returns collections of the specified type * @see MultiValueMap * @since 3.2 * @deprecated since 4.1, use {@link MultiValuedMap} instead */ @Deprecated public static > MultiValueMap multiValueMap(final Map map, final Class collectionClass) { return MultiValueMap.multiValueMap(map, collectionClass); } /** * Creates a multi-value map backed by the given map which returns collections created by the specified collection * factory. * * @param the key type * @param the value type * @param the collection class type * @param map the map to decorate * @param collectionFactory a factor which creates collection objects * @return a multi-value map backed by the given map which returns collections created by the specified collection * factory * @see MultiValueMap * @since 3.2 * @deprecated since 4.1, use {@link MultiValuedMap} instead */ @Deprecated public static > MultiValueMap multiValueMap(final Map map, final Factory collectionFactory) { return MultiValueMap.multiValueMap(map, collectionFactory); } /** * Returns a map that maintains the order of keys that are added backed by the given map. *

* If a key is added twice, the order is determined by the first add. The order is observed through the keySet, * values and entrySet. *

* * @param the key type * @param the value type * @param map the map to order, must not be null * @return an ordered map backed by the given map * @throws NullPointerException if the Map is null */ public static OrderedMap orderedMap(final Map map) { return ListOrderedMap.listOrderedMap(map); } /** * Populates a Map using the supplied {@code Transformer}s to transform the elements into keys and values. * * @param the key type * @param the value type * @param the type of object contained in the {@link Iterable} * @param map the {@code Map} to populate. * @param elements the {@code Iterable} containing the input values for the map. * @param keyTransformer the {@code Transformer} used to transform the element into a key value * @param valueTransformer the {@code Transformer} used to transform the element into a value * @throws NullPointerException if the map, elements or transformers are null */ public static void populateMap(final Map map, final Iterable elements, final Transformer keyTransformer, final Transformer valueTransformer) { for (final E temp : elements) { map.put(keyTransformer.apply(temp), valueTransformer.apply(temp)); } } /** * Populates a Map using the supplied {@code Transformer} to transform the elements into keys, using the * unaltered element as the value in the {@code Map}. * * @param the key type * @param the value type * @param map the {@code Map} to populate. * @param elements the {@code Iterable} containing the input values for the map. * @param keyTransformer the {@code Transformer} used to transform the element into a key value * @throws NullPointerException if the map, elements or transformer are null */ public static void populateMap(final Map map, final Iterable elements, final Transformer keyTransformer) { populateMap(map, elements, keyTransformer, TransformerUtils.nopTransformer()); } /** * Populates a MultiMap using the supplied {@code Transformer}s to transform the elements into keys and values. * * @param the key type * @param the value type * @param the type of object contained in the {@link Iterable} * @param map the {@code MultiMap} to populate. * @param elements the {@code Iterable} containing the input values for the map. * @param keyTransformer the {@code Transformer} used to transform the element into a key value * @param valueTransformer the {@code Transformer} used to transform the element into a value * @throws NullPointerException if the map, collection or transformers are null */ public static void populateMap(final MultiMap map, final Iterable elements, final Transformer keyTransformer, final Transformer valueTransformer) { for (final E temp : elements) { map.put(keyTransformer.apply(temp), valueTransformer.apply(temp)); } } /** * Populates a MultiMap using the supplied {@code Transformer} to transform the elements into keys, using the * unaltered element as the value in the {@code MultiMap}. * * @param the key type * @param the value type * @param map the {@code MultiMap} to populate. * @param elements the {@code Iterable} to use as input values for the map. * @param keyTransformer the {@code Transformer} used to transform the element into a key value * @throws NullPointerException if the map, elements or transformer are null */ public static void populateMap(final MultiMap map, final Iterable elements, final Transformer keyTransformer) { populateMap(map, elements, keyTransformer, TransformerUtils.nopTransformer()); } /** * Returns a predicated (validating) map backed by the given map. *

* Only objects that pass the tests in the given predicates can be added to the map. Trying to add an invalid object * results in an IllegalArgumentException. Keys must pass the key predicate, values must pass the value predicate. * It is important not to use the original map after invoking this method, as it is a backdoor for adding invalid * objects. *

* * @param the key type * @param the value type * @param map the map to predicate, must not be null * @param keyPred the predicate for keys, null means no check * @param valuePred the predicate for values, null means no check * @return a predicated map backed by the given map * @throws NullPointerException if the Map is null */ public static IterableMap predicatedMap(final Map map, final Predicate keyPred, final Predicate valuePred) { return PredicatedMap.predicatedMap(map, keyPred, valuePred); } /** * Returns a predicated (validating) sorted map backed by the given map. *

* Only objects that pass the tests in the given predicates can be added to the map. Trying to add an invalid object * results in an IllegalArgumentException. Keys must pass the key predicate, values must pass the value predicate. * It is important not to use the original map after invoking this method, as it is a backdoor for adding invalid * objects. *

* * @param the key type * @param the value type * @param map the map to predicate, must not be null * @param keyPred the predicate for keys, null means no check * @param valuePred the predicate for values, null means no check * @return a predicated map backed by the given map * @throws NullPointerException if the SortedMap is null */ public static SortedMap predicatedSortedMap(final SortedMap map, final Predicate keyPred, final Predicate valuePred) { return PredicatedSortedMap.predicatedSortedMap(map, keyPred, valuePred); } /** * Writes indentation to the given stream. * * @param out the stream to indent * @param indent the index of the indentation */ private static void printIndent(final PrintStream out, final int indent) { for (int i = 0; i < indent; i++) { out.print(INDENT_STRING); } } /** * Puts all the keys and values from the specified array into the map. *

* This method is an alternative to the {@link Map#putAll(java.util.Map)} method and constructors. It * allows you to build a map from an object array of various possible styles. *

*

* If the first entry in the object array implements {@link Map.Entry} or {@link KeyValue} then the key * and value are added from that object. If the first entry in the object array is an object array itself, then it * is assumed that index 0 in the sub-array is the key and index 1 is the value. Otherwise, the array is treated as * keys and values in alternate indices. *

*

* For example, to create a color map: *

*
     * Map colorMap = MapUtils.putAll(new HashMap(),
     *         new String[][] { { "RED", "#FF0000" }, { "GREEN", "#00FF00" }, { "BLUE", "#0000FF" } });
     * 
*

* or: *

*
     * Map colorMap = MapUtils.putAll(new HashMap(),
     *         new String[] { "RED", "#FF0000", "GREEN", "#00FF00", "BLUE", "#0000FF" });
     * 
*

* or: *

*
     * Map colorMap = MapUtils.putAll(new HashMap(), new Map.Entry[] { new DefaultMapEntry("RED", "#FF0000"),
     *         new DefaultMapEntry("GREEN", "#00FF00"), new DefaultMapEntry("BLUE", "#0000FF") });
     * 
* * @param the key type * @param the value type * @param map the map to populate, must not be null * @param array an array to populate from, null ignored * @return the input map * @throws NullPointerException if map is null * @throws IllegalArgumentException if sub-array or entry matching used and an entry is invalid * @throws ClassCastException if the array contents is mixed * @since 3.2 */ @SuppressWarnings("unchecked") // As per Javadoc throws CCE for invalid array contents public static Map putAll(final Map map, final Object[] array) { Objects.requireNonNull(map, "map"); if (array == null || array.length == 0) { return map; } final Object obj = array[0]; if (obj instanceof Map.Entry) { for (final Object element : array) { // cast ok here, type is checked above final Map.Entry entry = (Map.Entry) element; map.put(entry.getKey(), entry.getValue()); } } else if (obj instanceof KeyValue) { for (final Object element : array) { // cast ok here, type is checked above final KeyValue keyval = (KeyValue) element; map.put(keyval.getKey(), keyval.getValue()); } } else if (obj instanceof Object[]) { for (int i = 0; i < array.length; i++) { final Object[] sub = (Object[]) array[i]; if (sub == null || sub.length < 2) { throw new IllegalArgumentException("Invalid array element: " + i); } // these casts can fail if array has incorrect types map.put((K) sub[0], (V) sub[1]); } } else { for (int i = 0; i < array.length - 1;) { // these casts can fail if array has incorrect types map.put((K) array[i++], (V) array[i++]); } } return map; } /** * Protects against adding null values to a map. *

* This method checks the value being added to the map, and if it is null it is replaced by an empty string. *

*

* This could be useful if the map does not accept null values, or for receiving data from a source that may provide * null or empty string which should be held in the same way in the map. *

*

* Keys are not validated. Note that this method can be used to circumvent the map's value type at runtime. *

* * @param the key type * @param map the map to add to, must not be null * @param key the key * @param value the value, null converted to "" * @throws NullPointerException if the map is null */ public static void safeAddToMap(final Map map, final K key, final Object value) throws NullPointerException { Objects.requireNonNull(map, "map"); map.put(key, value == null ? "" : value); } /** * Gets the given map size or 0 if the map is null * * @param map a Map or null * @return the given map size or 0 if the map is null */ public static int size(final Map map) { return map == null ? 0 : map.size(); } /** * Returns a synchronized map backed by the given map. *

* You must manually synchronize on the returned buffer's iterator to avoid non-deterministic behavior: *

*
     * Map m = MapUtils.synchronizedMap(myMap);
     * Sets s = m.keySet(); // outside synchronized block
     * synchronized (m) { // synchronized on MAP!
     *     Iterator i = s.iterator();
     *     while (i.hasNext()) {
     *         process(i.next());
     *     }
     * }
     * 
*

* This method uses the implementation in {@link java.util.Collections Collections}. *

* * @param the key type * @param the value type * @param map the map to synchronize, must not be null * @return a synchronized map backed by the given map */ public static Map synchronizedMap(final Map map) { return Collections.synchronizedMap(map); } /** * Returns a synchronized sorted map backed by the given sorted map. *

* You must manually synchronize on the returned buffer's iterator to avoid non-deterministic behavior: *

*
     * Map m = MapUtils.synchronizedSortedMap(myMap);
     * Sets s = m.keySet(); // outside synchronized block
     * synchronized (m) { // synchronized on MAP!
     *     Iterator i = s.iterator();
     *     while (i.hasNext()) {
     *         process(i.next());
     *     }
     * }
     * 
*

* This method uses the implementation in {@link java.util.Collections Collections}. *

* * @param the key type * @param the value type * @param map the map to synchronize, must not be null * @return a synchronized map backed by the given map * @throws NullPointerException if the map is null */ public static SortedMap synchronizedSortedMap(final SortedMap map) { return Collections.synchronizedSortedMap(map); } /** * Creates a new HashMap using data copied from a ResourceBundle. * * @param resourceBundle the resource bundle to convert, must not be null * @return the HashMap containing the data * @throws NullPointerException if the bundle is null */ public static Map toMap(final ResourceBundle resourceBundle) { Objects.requireNonNull(resourceBundle, "resourceBundle"); final Enumeration enumeration = resourceBundle.getKeys(); final Map map = new HashMap<>(); while (enumeration.hasMoreElements()) { final String key = enumeration.nextElement(); final Object value = resourceBundle.getObject(key); map.put(key, value); } return map; } /** * Gets a new Properties object initialized with the values from a Map. A null input will return an empty properties * object. *

* A Properties object may only store non-null keys and values, thus if the provided map contains either a key or * value which is {@code null}, a {@link NullPointerException} will be thrown. *

* * @param the key type * @param the value type * @param map the map to convert to a Properties object * @return the properties object * @throws NullPointerException if a key or value in the provided map is {@code null} */ public static Properties toProperties(final Map map) { final Properties answer = new Properties(); if (map != null) { for (final Entry entry2 : map.entrySet()) { final Map.Entry entry = entry2; final Object key = entry.getKey(); final Object value = entry.getValue(); answer.put(key, value); } } return answer; } /** * Returns a transformed map backed by the given map. *

* This method returns a new map (decorating the specified map) that will transform any new entries added to it. * Existing entries in the specified map will not be transformed. If you want that behavior, see * {@link TransformedMap#transformedMap}. *

*

* Each object is passed through the transformers as it is added to the Map. It is important not to use the original * map after invoking this method, as it is a backdoor for adding untransformed objects. *

*

* If there are any elements already in the map being decorated, they are NOT transformed. *

* * @param the key type * @param the value type * @param map the map to transform, must not be null, typically empty * @param keyTransformer the transformer for the map keys, null means no transformation * @param valueTransformer the transformer for the map values, null means no transformation * @return a transformed map backed by the given map * @throws NullPointerException if the Map is null */ public static IterableMap transformedMap(final Map map, final Transformer keyTransformer, final Transformer valueTransformer) { return TransformedMap.transformingMap(map, keyTransformer, valueTransformer); } /** * Returns a transformed sorted map backed by the given map. *

* This method returns a new sorted map (decorating the specified map) that will transform any new entries added to * it. Existing entries in the specified map will not be transformed. If you want that behavior, see * {@link TransformedSortedMap#transformedSortedMap}. *

*

* Each object is passed through the transformers as it is added to the Map. It is important not to use the original * map after invoking this method, as it is a backdoor for adding untransformed objects. *

*

* If there are any elements already in the map being decorated, they are NOT transformed. *

* * @param the key type * @param the value type * @param map the map to transform, must not be null, typically empty * @param keyTransformer the transformer for the map keys, null means no transformation * @param valueTransformer the transformer for the map values, null means no transformation * @return a transformed map backed by the given map * @throws NullPointerException if the SortedMap is null */ public static SortedMap transformedSortedMap(final SortedMap map, final Transformer keyTransformer, final Transformer valueTransformer) { return TransformedSortedMap.transformingSortedMap(map, keyTransformer, valueTransformer); } /** * Returns an unmodifiable map backed by the given map. *

* This method uses the implementation in the decorators subpackage. *

* * @param the key type * @param the value type * @param map the map to make unmodifiable, must not be null * @return an unmodifiable map backed by the given map * @throws NullPointerException if the map is null */ public static Map unmodifiableMap(final Map map) { return UnmodifiableMap.unmodifiableMap(map); } /** * Returns an unmodifiable sorted map backed by the given sorted map. *

* This method uses the implementation in the decorators subpackage. *

* * @param the key type * @param the value type * @param map the sorted map to make unmodifiable, must not be null * @return an unmodifiable map backed by the given map * @throws NullPointerException if the map is null */ public static SortedMap unmodifiableSortedMap(final SortedMap map) { return UnmodifiableSortedMap.unmodifiableSortedMap(map); } /** * Prints the given map with nice line breaks. *

* This method prints a nicely formatted String describing the Map. Each map entry will be printed with key and * value. When the value is a Map, recursive behavior occurs. *

*

* This method is NOT thread-safe in any special way. You must manually synchronize on either this class or the * stream as required. *

* * @param out the stream to print to, must not be null * @param label The label to be used, may be {@code null}. If {@code null}, the label is not output. It * typically represents the name of the property in a bean or similar. * @param map The map to print, may be {@code null}. If {@code null}, the text 'null' is output. * @throws NullPointerException if the stream is {@code null} */ public static void verbosePrint(final PrintStream out, final Object label, final Map map) { verbosePrintInternal(out, label, map, new ArrayDeque<>(), false); } /** * Implementation providing functionality for {@link #debugPrint} and for {@link #verbosePrint}. This prints the * given map with nice line breaks. If the debug flag is true, it additionally prints the type of the object value. * If the contents of a map include the map itself, then the text (this Map) is printed out. If the * contents include a parent container of the map, the text (ancestor[i] Map) is printed, where it actually * indicates the number of levels which must be traversed in the sequential list of ancestors (e.g. father, * grandfather, great-grandfather, etc.). * * @param out the stream to print to * @param label the label to be used, may be {@code null}. If {@code null}, the label is not output. It * typically represents the name of the property in a bean or similar. * @param map the map to print, may be {@code null}. If {@code null}, the text 'null' is output * @param lineage a stack consisting of any maps in which the previous argument is contained. This is checked to * avoid infinite recursion when printing the output * @param debug flag indicating whether type names should be output. * @throws NullPointerException if the stream is {@code null} */ private static void verbosePrintInternal(final PrintStream out, final Object label, final Map map, final Deque> lineage, final boolean debug) { printIndent(out, lineage.size()); if (map == null) { if (label != null) { out.print(label); out.print(" = "); } out.println("null"); return; } if (label != null) { out.print(label); out.println(" = "); } printIndent(out, lineage.size()); out.println("{"); lineage.addLast(map); for (final Map.Entry entry : map.entrySet()) { final Object childKey = entry.getKey(); final Object childValue = entry.getValue(); if (childValue instanceof Map && !lineage.contains(childValue)) { verbosePrintInternal(out, childKey == null ? "null" : childKey, (Map) childValue, lineage, debug); } else { printIndent(out, lineage.size()); out.print(childKey); out.print(" = "); final int lineageIndex = IterableUtils.indexOf(lineage, PredicateUtils.equalPredicate(childValue)); if (lineageIndex == -1) { out.print(childValue); } else if (lineage.size() - 1 == lineageIndex) { out.print("(this Map)"); } else { out.print("(ancestor[" + (lineage.size() - 1 - lineageIndex - 1) + "] Map)"); } if (debug && childValue != null) { out.print(' '); out.println(childValue.getClass().getName()); } else { out.println(); } } } lineage.removeLast(); printIndent(out, lineage.size()); out.println(debug ? "} " + map.getClass().getName() : "}"); } /** * Don't allow instances. */ private MapUtils() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy