org.apache.commons.collections4.MapUtils Maven / Gradle / Ivy
Show all versions of commons-collections4 Show documentation
/*
* 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.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.SortedMap;
import java.util.TreeMap;
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 = " ";
/**
* MapUtils
should not normally be instantiated.
*/
private MapUtils() {}
// Type safe getters
//-------------------------------------------------------------------------
/**
* 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, null
if null map input
*/
public static V getObject(final Map super K, V> map, final K key) {
if (map != null) {
return map.get(key);
}
return null;
}
/**
* Gets a String from a Map in a null-safe manner.
*
* The String is obtained via 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, null
if null map input
*/
public static String getString(final Map super K, ?> map, final K key) {
if (map != null) {
final Object answer = map.get(key);
if (answer != null) {
return answer.toString();
}
}
return null;
}
/**
* Gets a Boolean from a Map in a null-safe manner.
*
* If the value is a Boolean
it is returned directly.
* If the value is a String
and it equals 'true' ignoring case
* then true
is returned, otherwise false
.
* If the value is a Number
an integer zero value returns
* false
and non-zero returns true
.
* Otherwise, 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, null
if null map input
*/
public static Boolean getBoolean(final Map super K, ?> 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;
}
/**
* Gets a Number from a Map in a null-safe manner.
*
* If the value is a Number
it is returned directly.
* If the value is a String
it is converted using
* {@link NumberFormat#parse(String)} on the system default formatter
* returning null
if the conversion fails.
* Otherwise, 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, null
if null map input
*/
public static Number getNumber(final Map super K, ?> 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;
}
/**
* 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, null
if null map input
*/
public static Byte getByte(final Map super K, ?> 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());
}
/**
* 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, null
if null map input
*/
public static Short getShort(final Map super K, ?> 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());
}
/**
* Gets a 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 a Integer, null
if null map input
*/
public static Integer getInteger(final Map super K, ?> 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());
}
/**
* 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, null
if null map input
*/
public static Long getLong(final Map super K, ?> 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());
}
/**
* 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, null
if null map input
*/
public static Float getFloat(final Map super K, ?> 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());
}
/**
* 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, null
if null map input
*/
public static Double getDouble(final Map super K, ?> 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());
}
/**
* Gets a Map from a Map in a null-safe manner.
*
* If the value returned from the specified map is not a Map then
* 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, null
if null map input
*/
public static Map, ?> getMap(final Map super K, ?> map, final K key) {
if (map != null) {
final Object answer = map.get(key);
if (answer != null && answer instanceof Map) {
return (Map, ?>) answer;
}
}
return null;
}
// Type safe getters with default values
//-------------------------------------------------------------------------
/**
* 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;
}
/**
* 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 super K, ?> map, final K key, final String defaultValue) {
String answer = getString(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Boolean defaultValue) {
Boolean answer = getBoolean(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Number defaultValue) {
Number answer = getNumber(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Byte defaultValue) {
Byte answer = getByte(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Short defaultValue) {
Short answer = getShort(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Integer defaultValue) {
Integer answer = getInteger(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Long defaultValue) {
Long answer = getLong(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Float defaultValue) {
Float answer = getFloat(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Double defaultValue) {
Double answer = getDouble(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
/**
* 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 super K, ?> map, final K key, final Map, ?> defaultValue) {
Map, ?> answer = getMap(map, key);
if (answer == null) {
answer = defaultValue;
}
return answer;
}
// Type safe primitive getters
//-------------------------------------------------------------------------
/**
* Gets a boolean from a Map in a null-safe manner.
*
* If the value is a Boolean
its value is returned.
* If the value is a String
and it equals 'true' ignoring case
* then true
is returned, otherwise false
.
* If the value is a Number
an integer zero value returns
* false
and non-zero returns true
.
* Otherwise, 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, false
if null map input
*/
public static boolean getBooleanValue(final Map super K, ?> map, final K key) {
return Boolean.TRUE.equals(getBoolean(map, key));
}
/**
* 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, 0
if null map input
*/
public static byte getByteValue(final Map super K, ?> map, final K key) {
final Byte byteObject = getByte(map, key);
if (byteObject == null) {
return 0;
}
return byteObject.byteValue();
}
/**
* 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, 0
if null map input
*/
public static short getShortValue(final Map super K, ?> map, final K key) {
final Short shortObject = getShort(map, key);
if (shortObject == null) {
return 0;
}
return shortObject.shortValue();
}
/**
* 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, 0
if null map input
*/
public static int getIntValue(final Map super K, ?> map, final K key) {
final Integer integerObject = getInteger(map, key);
if (integerObject == null) {
return 0;
}
return integerObject.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, 0L
if null map input
*/
public static long getLongValue(final Map super K, ?> map, final K key) {
final Long longObject = getLong(map, key);
if (longObject == null) {
return 0L;
}
return longObject.longValue();
}
/**
* 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, 0.0F
if null map input
*/
public static float getFloatValue(final Map super K, ?> map, final K key) {
final Float floatObject = getFloat(map, key);
if (floatObject == null) {
return 0f;
}
return floatObject.floatValue();
}
/**
* 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, 0.0
if null map input
*/
public static double getDoubleValue(final Map super K, ?> map, final K key) {
final Double doubleObject = getDouble(map, key);
if (doubleObject == null) {
return 0d;
}
return doubleObject.doubleValue();
}
// Type safe primitive getters with default values
//-------------------------------------------------------------------------
/**
* Gets a boolean from a Map in a null-safe manner,
* using the default value if the conversion fails.
*
* If the value is a Boolean
its value is returned.
* If the value is a String
and it equals 'true' ignoring case
* then true
is returned, otherwise false
.
* If the value is a Number
an integer zero value returns
* false
and non-zero returns true
.
* Otherwise, 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, defaultValue
if null map input
*/
public static boolean getBooleanValue(final Map super K, ?> map, final K key, final boolean defaultValue) {
final Boolean booleanObject = getBoolean(map, key);
if (booleanObject == null) {
return defaultValue;
}
return booleanObject.booleanValue();
}
/**
* 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, defaultValue
if null map input
*/
public static byte getByteValue(final Map super K, ?> map, final K key, final byte defaultValue) {
final Byte byteObject = getByte(map, key);
if (byteObject == null) {
return defaultValue;
}
return byteObject.byteValue();
}
/**
* 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, defaultValue
if null map input
*/
public static short getShortValue(final Map super K, ?> map, final K key, final short defaultValue) {
final Short shortObject = getShort(map, key);
if (shortObject == null) {
return defaultValue;
}
return shortObject.shortValue();
}
/**
* 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, defaultValue
if null map input
*/
public static int getIntValue(final Map super K, ?> map, final K key, final int defaultValue) {
final Integer integerObject = getInteger(map, key);
if (integerObject == null) {
return defaultValue;
}
return integerObject.intValue();
}
/**
* 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, defaultValue
if null map input
*/
public static long getLongValue(final Map super K, ?> map, final K key, final long defaultValue) {
final Long longObject = getLong(map, key);
if (longObject == null) {
return defaultValue;
}
return longObject.longValue();
}
/**
* 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, defaultValue
if null map input
*/
public static float getFloatValue(final Map super K, ?> map, final K key, final float defaultValue) {
final Float floatObject = getFloat(map, key);
if (floatObject == null) {
return defaultValue;
}
return floatObject.floatValue();
}
/**
* 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, defaultValue
if null map input
*/
public static double getDoubleValue(final Map super K, ?> map, final K key, final double defaultValue) {
final Double doubleObject = getDouble(map, key);
if (doubleObject == null) {
return defaultValue;
}
return doubleObject.doubleValue();
}
// Conversion methods
//-------------------------------------------------------------------------
/**
* Gets a new Properties object initialised 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;
}
/**
* Creates a new HashMap using data copied from a ResourceBundle.
*
* @param resourceBundle the resource bundle to convert, may not be null
* @return the hashmap containing the data
* @throws NullPointerException if the bundle is null
*/
public static Map toMap(final 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;
}
// Printing methods
//-------------------------------------------------------------------------
/**
* 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 behaviour 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 null
.
* If 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 null
.
* If null
, the text 'null' is output.
* @throws NullPointerException if the stream is null
*/
public static void verbosePrint(final PrintStream out, final Object label, final Map, ?> map) {
verbosePrintInternal(out, label, map, new ArrayDeque