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