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