| /* |
| * 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.Objects; |
| import java.util.Map.Entry; |
| 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. |
| * <p> |
| * It contains various type safe methods as well as other useful features like deep copying. |
| * </p> |
| * <p> |
| * It also provides the following decorators: |
| * </p> |
| * |
| * <ul> |
| * <li>{@link #fixedSizeMap(Map)} |
| * <li>{@link #fixedSizeSortedMap(SortedMap)} |
| * <li>{@link #lazyMap(Map,Factory)} |
| * <li>{@link #lazyMap(Map,Transformer)} |
| * <li>{@link #lazySortedMap(SortedMap,Factory)} |
| * <li>{@link #lazySortedMap(SortedMap,Transformer)} |
| * <li>{@link #predicatedMap(Map,Predicate,Predicate)} |
| * <li>{@link #predicatedSortedMap(SortedMap,Predicate,Predicate)} |
| * <li>{@link #transformedMap(Map, Transformer, Transformer)} |
| * <li>{@link #transformedSortedMap(SortedMap, Transformer, Transformer)} |
| * <li>{@link #multiValueMap( Map )} |
| * <li>{@link #multiValueMap( Map, Class )} |
| * <li>{@link #multiValueMap( Map, Factory )} |
| * </ul> |
| * |
| * @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 <K> The key type. |
| * @param <R> 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 <K, R> R applyDefaultFunction(final Map<? super K, ?> map, final K key, |
| final BiFunction<Map<? super K, ?>, K, R> getFunction, final Function<K, R> 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 <K> The key type. |
| * @param <R> 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 <K, R> R applyDefaultFunction(final Map<? super K, ?> map, final K key, |
| final BiFunction<Map<? super K, ?>, K, R> getFunction, final Function<K, R> 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 <K> The key type. |
| * @param <R> 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 <K, R> R applyDefaultValue(final Map<? super K, ?> map, final K key, |
| final BiFunction<Map<? super K, ?>, 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. |
| * <p> |
| * This method prints a nicely formatted String describing the Map. Each map entry will be printed with key, value |
| * and value classname. When the value is a Map, recursive behavior occurs. |
| * </p> |
| * <p> |
| * This method is NOT thread-safe in any special way. You must manually synchronize on either this class or the |
| * stream as required. |
| * </p> |
| * |
| * @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<Map<?, ?>>(), true); |
| } |
| |
| /** |
| * Returns an immutable empty map if the argument is {@code null}, or the argument itself otherwise. |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param map the map, possibly {@code null} |
| * @return an empty map if the argument is {@code null} |
| */ |
| public static <K, V> Map<K, V> emptyIfNull(final Map<K, V> map) { |
| return map == null ? Collections.<K, V>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 <K> the key type |
| * @param <V> 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 <K, V> IterableMap<K, V> fixedSizeMap(final Map<K, V> 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 <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> fixedSizeSortedMap(final SortedMap<K, V> map) { |
| return FixedSizeSortedMap.fixedSizeSortedMap(map); |
| } |
| |
| /** |
| * Gets a Boolean from a Map in a null-safe manner. |
| * <p> |
| * 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 <K> 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 <K> 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; |
| } |
| |
| /** |
| * Looks up the given key in the given map, converting the result into a boolean, using the default value if the |
| * conversion fails. |
| * |
| * @param <K> 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 <K> Boolean getBoolean(final Map<? super K, ?> 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 <K> 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 |
| */ |
| public static <K> Boolean getBoolean(final Map<? super K, ?> map, final K key, |
| final Function<K, Boolean> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getBoolean, defaultFunction); |
| } |
| |
| // Type safe primitive getters |
| // ------------------------------------------------------------------------- |
| /** |
| * Gets a boolean from a Map in a null-safe manner. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> 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 <K> boolean getBooleanValue(final Map<? super K, ?> map, final K key) { |
| return Boolean.TRUE.equals(getBoolean(map, key)); |
| } |
| |
| // 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. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> 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 <K> boolean getBooleanValue(final Map<? super K, ?> 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. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> boolean getBooleanValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Boolean> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getBoolean, defaultFunction, false).booleanValue(); |
| } |
| |
| /** |
| * Gets a Byte from a Map in a null-safe manner. |
| * <p> |
| * The Byte is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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()); |
| } |
| |
| /** |
| * Looks up the given key in the given map, converting the result into a byte, using the default value if the |
| * conversion fails. |
| * |
| * @param <K> 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 <K> Byte getByte(final Map<? super K, ?> 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 <K> 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 |
| */ |
| public static <K> Byte getByte(final Map<? super K, ?> map, final K key, final Function<K, Byte> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getByte, defaultFunction); |
| } |
| |
| /** |
| * Gets a byte from a Map in a null-safe manner. |
| * <p> |
| * The byte is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> byte getByteValue(final Map<? super K, ?> 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. |
| * <p> |
| * The byte is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> byte getByteValue(final Map<? super K, ?> 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. |
| * <p> |
| * The byte is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> byte getByteValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Byte> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getByte, defaultFunction, (byte) 0).byteValue(); |
| } |
| |
| /** |
| * Gets a Double from a Map in a null-safe manner. |
| * <p> |
| * The Double is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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()); |
| } |
| |
| /** |
| * Looks up the given key in the given map, converting the result into a double, using the default value if the |
| * conversion fails. |
| * |
| * @param <K> 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 <K> Double getDouble(final Map<? super K, ?> 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 <K> 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 |
| */ |
| public static <K> Double getDouble(final Map<? super K, ?> map, final K key, |
| final Function<K, Double> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getDouble, defaultFunction); |
| } |
| |
| /** |
| * Gets a double from a Map in a null-safe manner. |
| * <p> |
| * The double is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> double getDoubleValue(final Map<? super K, ?> 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. |
| * <p> |
| * The double is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> double getDoubleValue(final Map<? super K, ?> 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. |
| * <p> |
| * The double is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> double getDoubleValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Double> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getDouble, defaultFunction, 0d).doubleValue(); |
| } |
| |
| /** |
| * Gets a Float from a Map in a null-safe manner. |
| * <p> |
| * The Float is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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()); |
| } |
| |
| /** |
| * Looks up the given key in the given map, converting the result into a float, using the default value if the |
| * conversion fails. |
| * |
| * @param <K> 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 <K> Float getFloat(final Map<? super K, ?> 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 <K> 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 |
| */ |
| public static <K> Float getFloat(final Map<? super K, ?> map, final K key, |
| final Function<K, Float> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getFloat, defaultFunction); |
| } |
| |
| /** |
| * Gets a float from a Map in a null-safe manner. |
| * <p> |
| * The float is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> float getFloatValue(final Map<? super K, ?> 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. |
| * <p> |
| * The float is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> float getFloatValue(final Map<? super K, ?> 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. |
| * <p> |
| * The float is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> float getFloatValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Float> defaultFunction) { |
| return applyDefaultFunction(map, key, MapUtils::getFloat, defaultFunction, 0f).floatValue(); |
| } |
| |
| /** |
| * Gets a Integer from a Map in a null-safe manner. |
| * <p> |
| * The Integer is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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, {@code null} if null map input |
| */ |
| public static <K> 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()); |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> Integer getInteger(final Map<? super K, ?> map, final K key, |
| final Function<K, Integer> 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 <K> 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 <K> Integer getInteger(final Map<? super K, ?> 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. |
| * <p> |
| * The int is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> int getIntValue(final Map<? super K, ?> 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. |
| * <p> |
| * The int is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> int getIntValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Integer> 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. |
| * <p> |
| * The int is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> int getIntValue(final Map<? super K, ?> 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. |
| * <p> |
| * The Long is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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()); |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> Long getLong(final Map<? super K, ?> map, final K key, final Function<K, Long> 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 <K> 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 <K> Long getLong(final Map<? super K, ?> 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. |
| * <p> |
| * The long is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> long getLongValue(final Map<? super K, ?> 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. |
| * <p> |
| * The long is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> long getLongValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Long> 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. |
| * <p> |
| * The long is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> long getLongValue(final Map<? super K, ?> 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. |
| * <p> |
| * If the value returned from the specified map is not a Map then {@code null} is returned. |
| * </p> |
| * |
| * @param <K> 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 <K> 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; |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> Map<?, ?> getMap(final Map<? super K, ?> map, final K key, |
| final Function<K, Map<?, ?>> 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 <K> 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 <K> Map<?, ?> getMap(final Map<? super K, ?> 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. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> 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 <K> 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; |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> Number getNumber(final Map<? super K, ?> map, final K key, |
| final Function<K, Number> 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 <K> 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 <K> Number getNumber(final Map<? super K, ?> map, final K key, final Number defaultValue) { |
| return applyDefaultValue(map, key, MapUtils::getNumber, defaultValue); |
| } |
| |
| // ------------------------------------------------------------------------- |
| /** |
| * Gets from a Map in a null-safe manner. |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> V getObject(final Map<? super K, V> 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 <K> the key type |
| * @param <V> 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 <K, V> V getObject(final Map<K, V> 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. |
| * <p> |
| * The Short is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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()); |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> Short getShort(final Map<? super K, ?> map, final K key, |
| final Function<K, Short> 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 <K> 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 <K> Short getShort(final Map<? super K, ?> 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. |
| * <p> |
| * The short is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> short getShortValue(final Map<? super K, ?> 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. |
| * <p> |
| * The short is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 |
| */ |
| public static <K> short getShortValue(final Map<? super K, ?> map, final K key, |
| final Function<K, Short> 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. |
| * <p> |
| * The short is obtained from the results of {@link #getNumber(Map,Object)}. |
| * </p> |
| * |
| * @param <K> 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 <K> short getShortValue(final Map<? super K, ?> 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. |
| * <p> |
| * The String is obtained via {@code toString}. |
| * </p> |
| * |
| * @param <K> 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 <K> 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; |
| } |
| |
| /** |
| * 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 <K> 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 |
| */ |
| public static <K> String getString(final Map<? super K, ?> map, final K key, |
| final Function<K, String> 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 <K> 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 <K> String getString(final Map<? super K, ?> map, final K key, final String defaultValue) { |
| return applyDefaultValue(map, key, MapUtils::getString, defaultValue); |
| } |
| |
| // Misc |
| // ----------------------------------------------------------------------- |
| /** |
| * Inverts the supplied map returning a new HashMap such that the keys of the input are swapped with the values. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> Map<V, K> invertMap(final Map<K, V> map) { |
| Objects.requireNonNull(map, "map"); |
| final Map<V, K> out = new HashMap<>(map.size()); |
| for (final Entry<K, V> entry : map.entrySet()) { |
| out.put(entry.getValue(), entry.getKey()); |
| } |
| return out; |
| } |
| |
| /** |
| * Null-safe check if the specified map is empty. |
| * <p> |
| * Null returns true. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * Null returns false. |
| * </p> |
| * |
| * @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 !MapUtils.isEmpty(map); |
| } |
| |
| /** |
| * Get the specified {@link Map} as an {@link IterableMap}. |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param map to wrap if necessary. |
| * @return IterableMap<K, V> |
| * @throws NullPointerException if map is null |
| * @since 4.0 |
| */ |
| public static <K, V> IterableMap<K, V> iterableMap(final Map<K, V> map) { |
| Objects.requireNonNull(map, "map"); |
| return map instanceof IterableMap ? (IterableMap<K, V>) map : new AbstractMapDecorator<K, V>(map) { |
| // empty |
| }; |
| } |
| |
| /** |
| * Get the specified {@link SortedMap} as an {@link IterableSortedMap}. |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> IterableSortedMap<K, V> iterableSortedMap(final SortedMap<K, V> sortedMap) { |
| Objects.requireNonNull(sortedMap, "sortedMap"); |
| return sortedMap instanceof IterableSortedMap ? (IterableSortedMap<K, V>) sortedMap |
| : new AbstractSortedMapDecorator<K, V>(sortedMap) { |
| // empty |
| }; |
| } |
| |
| /** |
| * Returns a "lazy" map whose values will be created on demand. |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * For instance: |
| * </p> |
| * <pre> |
| * Factory factory = new Factory() { |
| * public Object create() { |
| * return new Date(); |
| * } |
| * } |
| * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory); |
| * Object obj = lazyMap.get("test"); |
| * </pre> |
| * |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> IterableMap<K, V> lazyMap(final Map<K, V> map, final Factory<? extends V> factory) { |
| return LazyMap.lazyMap(map, factory); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| /** |
| * Returns a "lazy" map whose values will be created on demand. |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * For instance: |
| * </p> |
| * <pre> |
| * 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"); |
| * </pre> |
| * |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> IterableMap<K, V> lazyMap(final Map<K, V> map, |
| final Transformer<? super K, ? extends V> transformerFactory) { |
| return LazyMap.lazyMap(map, transformerFactory); |
| } |
| |
| /** |
| * Returns a "lazy" sorted map whose values will be created on demand. |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * For instance: |
| * </p> |
| * <pre> |
| * Factory factory = new Factory() { |
| * public Object create() { |
| * return new Date(); |
| * } |
| * } |
| * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory); |
| * Object obj = lazy.get("test"); |
| * </pre> |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> lazySortedMap(final SortedMap<K, V> map, final Factory<? extends V> factory) { |
| return LazySortedMap.lazySortedMap(map, factory); |
| } |
| |
| /** |
| * Returns a "lazy" sorted map whose values will be created on demand. |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * For instance: |
| * </p> |
| * <pre> |
| * 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"); |
| * </pre> |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> lazySortedMap(final SortedMap<K, V> map, |
| final Transformer<? super K, ? extends V> transformerFactory) { |
| return LazySortedMap.lazySortedMap(map, transformerFactory); |
| } |
| |
| /** |
| * Creates a mult-value map backed by the given map which returns collections of type ArrayList. |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> MultiValueMap<K, V> multiValueMap(final Map<K, ? super Collection<V>> map) { |
| return MultiValueMap.<K, V>multiValueMap(map); |
| } |
| |
| /** |
| * Creates a multi-value map backed by the given map which returns collections of the specified type. |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param <C> 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 <K, V, C extends Collection<V>> MultiValueMap<K, V> multiValueMap(final Map<K, C> map, |
| final Class<C> 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 <K> the key type |
| * @param <V> the value type |
| * @param <C> 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 <K, V, C extends Collection<V>> MultiValueMap<K, V> multiValueMap(final Map<K, C> map, |
| final Factory<C> collectionFactory) { |
| return MultiValueMap.multiValueMap(map, collectionFactory); |
| } |
| |
| /** |
| * Returns a map that maintains the order of keys that are added backed by the given map. |
| * <p> |
| * If a key is added twice, the order is determined by the first add. The order is observed through the keySet, |
| * values and entrySet. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> OrderedMap<K, V> orderedMap(final Map<K, V> map) { |
| return ListOrderedMap.listOrderedMap(map); |
| } |
| |
| /** |
| * Populates a Map using the supplied {@code Transformer}s to transform the elements into keys and values. |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param <E> 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 <K, V, E> void populateMap(final Map<K, V> map, final Iterable<? extends E> elements, |
| final Transformer<E, K> keyTransformer, final Transformer<E, V> valueTransformer) { |
| final Iterator<? extends E> iter = elements.iterator(); |
| while (iter.hasNext()) { |
| final E temp = iter.next(); |
| map.put(keyTransformer.transform(temp), valueTransformer.transform(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 <K> the key type |
| * @param <V> 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 <K, V> void populateMap(final Map<K, V> map, final Iterable<? extends V> elements, |
| final Transformer<V, K> keyTransformer) { |
| populateMap(map, elements, keyTransformer, TransformerUtils.<V>nopTransformer()); |
| } |
| |
| /** |
| * Populates a MultiMap using the supplied {@code Transformer}s to transform the elements into keys and values. |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param <E> 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 <K, V, E> void populateMap(final MultiMap<K, V> map, final Iterable<? extends E> elements, |
| final Transformer<E, K> keyTransformer, final Transformer<E, V> valueTransformer) { |
| final Iterator<? extends E> iter = elements.iterator(); |
| while (iter.hasNext()) { |
| final E temp = iter.next(); |
| map.put(keyTransformer.transform(temp), valueTransformer.transform(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 <K> the key type |
| * @param <V> 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 <K, V> void populateMap(final MultiMap<K, V> map, final Iterable<? extends V> elements, |
| final Transformer<V, K> keyTransformer) { |
| populateMap(map, elements, keyTransformer, TransformerUtils.<V>nopTransformer()); |
| } |
| |
| /** |
| * Returns a predicated (validating) map backed by the given map. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> IterableMap<K, V> predicatedMap(final Map<K, V> map, final Predicate<? super K> keyPred, |
| final Predicate<? super V> valuePred) { |
| return PredicatedMap.predicatedMap(map, keyPred, valuePred); |
| } |
| |
| /** |
| * Returns a predicated (validating) sorted map backed by the given map. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> predicatedSortedMap(final SortedMap<K, V> map, |
| final Predicate<? super K> keyPred, final Predicate<? super V> 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. |
| * <p> |
| * This method is an alternative to the {@link java.util.Map#putAll(java.util.Map)} method and constructors. It |
| * allows you to build a map from an object array of various possible styles. |
| * </p> |
| * <p> |
| * If the first entry in the object array implements {@link java.util.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. |
| * </p> |
| * <p> |
| * For example, to create a color map: |
| * </p> |
| * |
| * <pre> |
| * Map colorMap = MapUtils.putAll(new HashMap(), |
| * new String[][] { { "RED", "#FF0000" }, { "GREEN", "#00FF00" }, { "BLUE", "#0000FF" } }); |
| * </pre> |
| * |
| * <p> |
| * or: |
| * </p> |
| * |
| * <pre> |
| * Map colorMap = MapUtils.putAll(new HashMap(), |
| * new String[] { "RED", "#FF0000", "GREEN", "#00FF00", "BLUE", "#0000FF" }); |
| * </pre> |
| * |
| * <p> |
| * or: |
| * </p> |
| * |
| * <pre> |
| * Map colorMap = MapUtils.putAll(new HashMap(), new Map.Entry[] { new DefaultMapEntry("RED", "#FF0000"), |
| * new DefaultMapEntry("GREEN", "#00FF00"), new DefaultMapEntry("BLUE", "#0000FF") }); |
| * </pre> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> Map<K, V> putAll(final Map<K, V> 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<K, V> entry = (Map.Entry<K, V>) 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<K, V> keyval = (KeyValue<K, V>) 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. |
| * <p> |
| * This method checks the value being added to the map, and if it is null it is replaced by an empty string. |
| * </p> |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * Keys are not validated. Note that this method can be used to circumvent the map's value type at runtime. |
| * </p> |
| * |
| * @param <K> 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 <K> void safeAddToMap(final Map<? super K, Object> 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. |
| * <p> |
| * You must manually synchronize on the returned buffer's iterator to avoid non-deterministic behavior: |
| * </p> |
| * |
| * <pre> |
| * Map m = MapUtils.synchronizedMap(myMap); |
| * Set s = m.keySet(); // outside synchronized block |
| * synchronized (m) { // synchronized on MAP! |
| * Iterator i = s.iterator(); |
| * while (i.hasNext()) { |
| * process(i.next()); |
| * } |
| * } |
| * </pre> |
| * |
| * <p> |
| * This method uses the implementation in {@link java.util.Collections Collections}. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> the value type |
| * @param map the map to synchronize, must not be null |
| * @return a synchronized map backed by the given map |
| */ |
| public static <K, V> Map<K, V> synchronizedMap(final Map<K, V> map) { |
| return Collections.synchronizedMap(map); |
| } |
| |
| // ----------------------------------------------------------------------- |
| /** |
| * Returns a synchronized sorted map backed by the given sorted map. |
| * <p> |
| * You must manually synchronize on the returned buffer's iterator to avoid non-deterministic behavior: |
| * </p> |
| * |
| * <pre> |
| * Map m = MapUtils.synchronizedSortedMap(myMap); |
| * Set s = m.keySet(); // outside synchronized block |
| * synchronized (m) { // synchronized on MAP! |
| * Iterator i = s.iterator(); |
| * while (i.hasNext()) { |
| * process(i.next()); |
| * } |
| * } |
| * </pre> |
| * |
| * <p> |
| * This method uses the implementation in {@link java.util.Collections Collections}. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> synchronizedSortedMap(final SortedMap<K, V> 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<String, Object> toMap(final ResourceBundle resourceBundle) { |
| Objects.requireNonNull(resourceBundle, "resourceBundle"); |
| final Enumeration<String> enumeration = resourceBundle.getKeys(); |
| final Map<String, Object> 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 initialised with the values from a Map. A null input will return an empty properties |
| * object. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> Properties toProperties(final Map<K, V> map) { |
| final Properties answer = new Properties(); |
| if (map != null) { |
| for (final Entry<K, V> 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. |
| * <p> |
| * 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}. |
| * </p> |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * If there are any elements already in the map being decorated, they are NOT transformed. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> IterableMap<K, V> transformedMap(final Map<K, V> map, |
| final Transformer<? super K, ? extends K> keyTransformer, |
| final Transformer<? super V, ? extends V> valueTransformer) { |
| return TransformedMap.transformingMap(map, keyTransformer, valueTransformer); |
| } |
| |
| /** |
| * Returns a transformed sorted map backed by the given map. |
| * <p> |
| * 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}. |
| * </p> |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * If there are any elements already in the map being decorated, they are NOT transformed. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> transformedSortedMap(final SortedMap<K, V> map, |
| final Transformer<? super K, ? extends K> keyTransformer, |
| final Transformer<? super V, ? extends V> valueTransformer) { |
| return TransformedSortedMap.transformingSortedMap(map, keyTransformer, valueTransformer); |
| } |
| |
| /** |
| * Returns an unmodifiable map backed by the given map. |
| * <p> |
| * This method uses the implementation in the decorators subpackage. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> Map<K, V> unmodifiableMap(final Map<? extends K, ? extends V> map) { |
| return UnmodifiableMap.unmodifiableMap(map); |
| } |
| |
| /** |
| * Returns an unmodifiable sorted map backed by the given sorted map. |
| * <p> |
| * This method uses the implementation in the decorators subpackage. |
| * </p> |
| * |
| * @param <K> the key type |
| * @param <V> 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 <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> map) { |
| return UnmodifiableSortedMap.unmodifiableSortedMap(map); |
| } |
| |
| // Printing methods |
| // ------------------------------------------------------------------------- |
| /** |
| * Prints the given map with nice line breaks. |
| * <p> |
| * 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. |
| * </p> |
| * <p> |
| * This method is NOT thread-safe in any special way. You must manually synchronize on either this class or the |
| * stream as required. |
| * </p> |
| * |
| * @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<Map<?, ?>>(), 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 <em>(this Map)</em> is printed out. If the |
| * contents include a parent container of the map, the text <em>(ancestor[i] Map)</em> is printed, where i 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<Map<?, ?>> 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() : "}"); |
| } |
| |
| /** |
| * {@code MapUtils} should not normally be instantiated. |
| */ |
| private MapUtils() { |
| } |
| |
| } |