View Javadoc

1   /*
2   
3       dsh-collect  Collection and map utility classes.
4       Copyright (c) 2008-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.collect;
25  
26  import java.util.Collections;
27  import java.util.Comparator;
28  import java.util.Map;
29  import java.util.HashMap;
30  import java.util.NavigableMap;
31  import java.util.SortedMap;
32  import java.util.TreeMap;
33  
34  import java.util.concurrent.ConcurrentMap;
35  import java.util.concurrent.ConcurrentHashMap;
36  import java.util.concurrent.ConcurrentSkipListMap;
37  
38  import org.cliffc.high_scale_lib.NonBlockingHashMap;
39  import org.cliffc.high_scale_lib.NonBlockingHashMapLong;
40  
41  import com.google.common.collect.ImmutableMap;
42  import com.google.common.collect.ImmutableSortedMap;
43  
44  /**
45   * Static utility methods for Maps.
46   *
47   * @author  Michael Heuer
48   * @version $Revision$ $Date$
49   */
50  public final class Maps
51  {
52  
53      /**
54       * Private no-arg constructor.
55       */
56      private Maps()
57      {
58          // empty
59      }
60  
61  
62      /**
63       * Create and return a new empty map.  Delegates to <code>Collections.emptyMap()</code>.
64       *
65       * @param <K> key type
66       * @param <V> value type
67       * @return a new empty map
68       */
69      public static <K, V> Map<K, V> emptyMap()
70      {
71          return Collections.<K, V>emptyMap();
72      }
73  
74      /**
75       * Create and return a new instance of Map.
76       *
77       * @param <K> key type
78       * @param <V> value type
79       * @return a new instance of Map
80       */
81      public static <K, V> Map<K, V> createMap()
82      {
83          return new HashMap<K, V>();
84      }
85  
86      /**
87       * Create and return a new instance of Map with the specified initial capacity.
88       *
89       * @param <K> key type
90       * @param <V> value type
91       * @param initialCapacity initial capacity
92       * @return a new instance of Map with the specified initial capacity
93       */
94      public static <K, V> Map<K, V> createMap(final int initialCapacity)
95      {
96          return new HashMap<K, V>(initialCapacity);
97      }
98  
99      /**
100      * Create and return a new instance of Map with the specified initial capacity
101      * and load factor.
102      *
103      * @param <K> key type
104      * @param <V> value type
105      * @param initialCapacity initial capacity
106      * @param loadFactor load factor
107      * @return a new instance of Map with the specified initial capacity
108      *    and load factor
109      */
110     public static <K, V> Map<K, V> createMap(final int initialCapacity, final float loadFactor)
111     {
112         return new HashMap<K, V>(initialCapacity, loadFactor);
113     }
114 
115     /**
116      * Create and return a new instance of Map with the same mappings as the
117      * specified map. The map is created with default load factor (0.75) and an
118      * initial capacity sufficient to hold the mappings in the specified map.
119      *
120      * @param <K> key type
121      * @param <V> value type
122      * @param map map to copy mappings from
123      * @return a new instance of Map with the same mappings as the
124      *    specified map
125      */
126     public static <K, V> Map<K, V> createMap(final Map<? extends K, ? extends V> map)
127     {
128         return new HashMap<K, V>(map);
129     }
130 
131     /**
132      * Create and return a new synchronized (thread-safe) instance of Map.  It is
133      * imperative that the user manually synchronize on the returned map when iterating
134      * over any of its collection views:
135      * <pre>
136      * Map m = Maps.newSynchronizedMap();
137      * ...
138      * Set s = m.keySet();  // Needn't be in synchronized block
139      * ...
140      * synchronized(m)  // Synchronizing on m, not s!
141      * {
142      *   Iterator i = s.iterator(); // Must be in synchronized block
143      *   while (i.hasNext())
144      *   {
145      *      foo(i.next());
146      *   }
147      * }
148      * </pre>
149      * Failure to follow this advice may result in non-deterministic behavior.
150      *
151      * @param <K> key type
152      * @param <V> value type
153      * @return a new synchronized (thread-safe) instance of Map
154      */
155     public static <K, V> Map<K, V> createSynchronizedMap()
156     {
157         return Collections.synchronizedMap(new HashMap<K, V>());
158     }
159 
160     /**
161      * Create and return a new synchronized (thread-safe) instance of Map with
162      * the specified initial capacity.  It is imperative that the user manually
163      * synchronize on the returned map when iterating over any of its collection
164      * views:
165      * <pre>
166      * Map m = Maps.newSynchronizedMap(10);
167      * ...
168      * Set s = m.keySet();  // Needn't be in synchronized block
169      * ...
170      * synchronized(m)  // Synchronizing on m, not s!
171      * {
172      *   Iterator i = s.iterator(); // Must be in synchronized block
173      *   while (i.hasNext())
174      *   {
175      *      foo(i.next());
176      *   }
177      * }
178      * </pre>
179      * Failure to follow this advice may result in non-deterministic behavior.
180      *
181      * @param <K> key type
182      * @param <V> value type
183      * @param initialCapacity initial capacity
184      * @return a new synchronized (thread-safe) instance of Map with
185      *    the specified initial capacity
186      */
187     public static <K, V> Map<K, V> createSynchronizedMap(final int initialCapacity)
188     {
189         return Collections.synchronizedMap(new HashMap<K, V>(initialCapacity));
190     }
191 
192     /**
193      * Create and return a new synchronized (thread-safe) instance of Map with
194      * the specified initial capacity and load factor.  It is imperative that the
195      * user manually synchronize on the returned map when iterating over any of
196      * its collection views:
197      * <pre>
198      * Map m = Maps.newSynchronizedMap(10, 0.80);
199      * ...
200      * Set s = m.keySet();  // Needn't be in synchronized block
201      * ...
202      * synchronized(m)  // Synchronizing on m, not s!
203      * {
204      *   Iterator i = s.iterator(); // Must be in synchronized block
205      *   while (i.hasNext())
206      *   {
207      *      foo(i.next());
208      *   }
209      * }
210      * </pre>
211      * Failure to follow this advice may result in non-deterministic behavior.
212      *
213      * @param <K> key type
214      * @param <V> value type
215      * @param initialCapacity initial capacity
216      * @param loadFactor load factor
217      * @return a new synchronized (thread-safe) instance of Map with
218      *    the specified intial capacity and load factor
219      */
220     public static <K, V> Map<K, V> createSynchronizedMap(final int initialCapacity, final float loadFactor)
221     {
222         return Collections.synchronizedMap(new HashMap<K, V>(initialCapacity, loadFactor));
223     }
224 
225     /**
226      * Create and return a new synchronized (thread-safe) instance of Map with
227      * the same mappings as the specified map. The map is created with default load
228      * factor (0.75) and an initial capacity sufficient to hold the mappings in the
229      * specified map.  It is imperative that the user manually synchronize on the
230      * returned map when iterating over any of its collection views:
231      * <pre>
232      * Map m = Maps.newSynchronizedMap(map);
233      * ...
234      * Set s = m.keySet();  // Needn't be in synchronized block
235      * ...
236      * synchronized(m)  // Synchronizing on m, not s!
237      * {
238      *   Iterator i = s.iterator(); // Must be in synchronized block
239      *   while (i.hasNext())
240      *   {
241      *      foo(i.next());
242      *   }
243      * }
244      * </pre>
245      * Failure to follow this advice may result in non-deterministic behavior.
246      *
247      * @param <K> key type
248      * @param <V> value type
249      * @param map map to copy mappings from
250      * @return a new synchronized (thread-safe) instance of Map with
251      *    the same mappings as the specified map
252      */
253     public static <K, V> Map<K, V> createSynchronizedMap(final Map<? extends K, ? extends V> map)
254     {
255         return Collections.synchronizedMap(new HashMap<K, V>(map));
256     }
257 
258     /**
259      * Create and return a new instance of ConcurrentMap.
260      *
261      * @param <K> key type
262      * @param <V> value type
263      * @return a new instance of ConcurrentMap
264      */
265     public static <K, V> ConcurrentMap<K, V> createConcurrentMap()
266     {
267         return new ConcurrentHashMap<K, V>();
268     }
269 
270     /**
271      * Create and return a new instance of ConcurrentMap with the specified initial capacity.
272      *
273      * @param <K> key type
274      * @param <V> value type
275      * @param initialCapacity initial capacity
276      * @return a new instance of ConcurrentMap with the specified initial capacity
277      */
278     public static <K, V> ConcurrentMap<K, V> createConcurrentMap(final int initialCapacity)
279     {
280         return new ConcurrentHashMap<K, V>(initialCapacity);
281     }
282 
283     /**
284      * Create and return a new instance of ConcurrentMap with the specified initial capacity
285      * and load factor.
286      *
287      * @param <K> key type
288      * @param <V> value type
289      * @param initialCapacity initial capacity
290      * @param loadFactor load factor
291      * @return a new instance of ConcurrentMap with the specified initial capacity
292      *    and load factor
293      */
294     public static <K, V> ConcurrentMap<K, V> createConcurrentMap(final int initialCapacity,
295                                                               final float loadFactor)
296     {
297         return new ConcurrentHashMap<K, V>(initialCapacity, loadFactor);
298     }
299 
300     /**
301      * Create and return a new instance of ConcurrentMap with the specified initial capacity,
302      * load factor, and concurrency level.
303      *
304      * @param <K> key type
305      * @param <V> value type
306      * @param initialCapacity initial capacity
307      * @param loadFactor load factor
308      * @param concurrencyLevel concurrency level
309      * @return a new instance of ConcurrentMap with the specified initial capacity
310      *    load factor, and concurrency level
311      */
312     public static <K, V> ConcurrentMap<K, V> createConcurrentMap(final int initialCapacity,
313                                                               final float loadFactor,
314                                                               final int concurrencyLevel)
315     {
316         return new ConcurrentHashMap<K, V>(initialCapacity, loadFactor, concurrencyLevel);
317     }
318 
319     /**
320      * Create and return a new instance of ConcurrentMap with the same mappings as the
321      * specified map. The concurrent map is created with default load factor (0.75) and an
322      * initial capacity sufficient to hold the mappings in the specified map.
323      *
324      * @param <K> key type
325      * @param <V> value type
326      * @param map map to copy mappings from, must not be null
327      * @return a new instance of ConcurrentMap with the same mappings as the
328      *    specified map
329      */
330     public static <K, V> ConcurrentMap<K, V> createConcurrentMap(final Map<? extends K, ? extends V> map)
331     {
332         return new ConcurrentHashMap<K, V>(map);
333     }
334 
335     /**
336      * Create and return a new non-blocking implementation of ConcurrentMap.
337      *
338      * @param <K> key type
339      * @param <V> value type
340      * @return a new non-blocking implementation of ConcurrentMap
341      */
342     public static <K, V> ConcurrentMap<K, V> createNonBlockingMap()
343     {
344         return new NonBlockingHashMap<K, V>();
345     }
346 
347     /**
348      * Create and return a new non-blocking implementation of ConcurrentMap with the
349      * specified initial capacity.
350      *
351      * @param <K> key type
352      * @param <V> value type
353      * @param initialCapacity initial capacity
354      * @return a new non-blocking implementation of ConcurrentMap with the
355      *    specified initial capacity
356      */
357     public static <K, V> ConcurrentMap<K, V> createNonBlockingMap(final int initialCapacity)
358     {
359         return new NonBlockingHashMap<K, V>(initialCapacity);
360     }
361 
362     /**
363      * Create and return a new non-blocking implementation of ConcurrentMap with
364      * <code>Long</code>s as keys.
365      *
366      * @param <V> value type
367      * @return a new non-blocking implementation of ConcurrentMap with
368      *    <code>Long</code>s as keys
369      */
370     public static <V> ConcurrentMap<Long, V> createLongNonBlockingMap()
371     {
372         return new NonBlockingHashMapLong<V>();
373     }
374 
375     /**
376      * Create and return a new non-blocking implementation of ConcurrentMap with
377      * <code>Long</code>s as keys.
378      *
379      * @param <V> value type
380      * @param optimizeForSpace true if the implementation should optimize for space
381      * @return a new non-blocking implementation of ConcurrentMap with
382      *    <code>Long</code>s as keys
383      */
384     public static <V> ConcurrentMap<Long, V> createLongNonBlockingMap(final boolean optimizeForSpace)
385     {
386         return new NonBlockingHashMapLong<V>(optimizeForSpace);
387     }
388 
389     /**
390      * Create and return a new non-blocking implementation of ConcurrentMap with
391      * the specified initial capacity and <code>Long</code>s as keys.
392      *
393      * @param <V> value type
394      * @param initialCapacity initial capacity
395      * @return a new non-blocking implementation of ConcurrentMap with
396      *    the specified initial capacity and <code>Long</code>s as keys
397      */
398     public static <V> ConcurrentMap<Long, V> createLongNonBlockingMap(final int initialCapacity)
399     {
400         return new NonBlockingHashMapLong<V>(initialCapacity);
401     }
402 
403     /**
404      * Create and return a new non-blocking implementation of ConcurrentMap with
405      * the specified initial capacity and <code>Long</code>s as keys.
406      *
407      * @param <V> value type
408      * @param initialCapacity initial capacity
409      * @param optimizeForSpace true if this implementation should optimize for space
410      * @return a new non-blocking implementation of ConcurrentMap with
411      *    the specified initial capacity and <code>Long</code>s as keys
412      */
413     public static <V> ConcurrentMap<Long, V> createLongNonBlockingMap(final int initialCapacity,
414                                                                    final boolean optimizeForSpace)
415     {
416         return new NonBlockingHashMapLong<V>(initialCapacity, optimizeForSpace);
417     }
418 
419     /**
420      * Create and return a new instance of ConcurrentSkipListMap sorted according
421      * to the natural ordering of its keys.
422      *
423      * @param <K> key type
424      * @param <V> value type
425      * @return a new instance of ConcurrentSkipListMap sorted according
426      *    to the natural ordering of its keys
427      */
428     public static <K, V> ConcurrentSkipListMap<K, V> createConcurrentSkipListMap()
429     {
430         return new ConcurrentSkipListMap<K, V>();
431     }
432 
433     /**
434      * Create and return a new instance of ConcurrentSkipListMap sorted according
435      * to the specified comparator.
436      *
437      * @param <K> key type
438      * @param <V> value type
439      * @param comparator comparator that will be used to order this map, or
440      *    <code>null</code> to use the natural ordering of its keys
441      * @return a new instance of ConcurrentSkipListMap sorted according
442      *    to the specified comparator
443      */
444     public static <K, V> ConcurrentSkipListMap<K, V> createConcurrentSkipListMap(final Comparator<? super K> comparator)
445     {
446         return new ConcurrentSkipListMap<K, V>(comparator);
447     }
448 
449     /**
450      * Create and return a new instance of ConcurrentSkipListMap containing the
451      * same mappings as the specified map and sorted according to the natural ordering of
452      * its keys.
453      *
454      * @param <K> key type
455      * @param <V> value type
456      * @param map map to copy mappings from, must not be null
457      * @return a new instance of ConcurrentSkipListMap containing the
458      *    same mappings as the specified map and sorted according to the natural ordering of
459      *    its keys
460      */
461     public static <K, V> ConcurrentSkipListMap<K, V> createConcurrentSkipListMap(final Map<? extends K, ? extends V> map)
462     {
463         return new ConcurrentSkipListMap<K, V>(map);
464     }
465 
466     /**
467      * Create and return a new instance of ConcurrentSkipListMap containing the
468      * same mappings and using the same ordering as the specified sorted map.
469      *
470      * @param <K> key type
471      * @param <V> value type
472      * @param sortedMap sorted map to copy mappings and ordering from, must not be null
473      * @return a new instance of ConcurrentSkipListMap containing the
474      *    same mappings and using the same ordering as the specified sorted map
475      */
476     public static <K, V> ConcurrentSkipListMap<K, V> createConcurrentSkipListMap(final SortedMap<K, ? extends V> sortedMap)
477     {
478         return new ConcurrentSkipListMap<K, V>(sortedMap);
479     }
480 
481     /**
482      * Create and return a new instance of SortedMap using the natural ordering of its keys.
483      *
484      * @param <K> key type
485      * @param <V> value type
486      * @return a new instance of SortedMap using the natural ordering of its keys
487      */
488     public static <K, V> SortedMap<K, V> createSortedMap()
489     {
490         return new TreeMap<K, V>();
491     }
492 
493     /**
494      * Create and return a new instance of SortedMap ordered according to the specified comparator.
495      *
496      * @param <K> key type
497      * @param <V> value type
498      * @param comparator comparator used to order this map, or <code>null</code> to use the
499      *    natural ordering of its keys
500      * @return a new instance of SortedMap ordered according to the specified comparator
501      */
502     public static <K, V> SortedMap<K, V> createSortedMap(final Comparator<? super K> comparator)
503     {
504         return new TreeMap<K, V>(comparator);
505     }
506 
507     /**
508      * Create and return a new instance of SortedMap containing the same mappings as the specified
509      * map ordered according to the natural ordering of its keys.
510      *
511      * @param <K> key type
512      * @param <V> value type
513      * @param map map to copy mappings from, must not be null
514      * @return a new instance of SortedMap containing the same mappings as the specified
515      *    map ordered according to the natural ordering of its keys
516      */
517     public static <K, V> SortedMap<K, V> createSortedMap(final Map<? extends K, ? extends V> map)
518     {
519         return new TreeMap<K, V>(map);
520     }
521 
522     /**
523      * Create and return a new instance of SortedMap containing the same mappings and the same
524      * ordering as the specified sorted map.
525      *
526      * @param <K> key type
527      * @param <V> value type
528      * @param sortedMap sorted map to copy mappings and comparator from, must not be null
529      * @return a new instance of SortedMap containing the same mappings and the same
530      *    ordering as the specified sorted map
531      */
532     public static <K, V> SortedMap<K, V> createSortedMap(final SortedMap<K, ? extends V> sortedMap)
533     {
534         return new TreeMap<K, V>(sortedMap);
535     }
536 
537     /**
538      * Create and return a new instance of NavigableMap using the natural ordering of its keys.
539      *
540      * @param <K> key type
541      * @param <V> value type
542      * @return a new instance of NavigableMap using the natural ordering of its keys
543      */
544     public static <K, V> NavigableMap<K, V> createNavigableMap()
545     {
546         return new TreeMap<K, V>();
547     }
548 
549     /**
550      * Create and return a new instance of NavigableMap ordered according to the specified comparator.
551      *
552      * @param <K> key type
553      * @param <V> value type
554      * @param comparator comparator used to order this map, or <code>null</code> to use the
555      *    natural ordering of its keys
556      * @return a new instance of NavigableMap ordered according to the specified comparator
557      */
558     public static <K, V> NavigableMap<K, V> createNavigableMap(final Comparator<? super K> comparator)
559     {
560         return new TreeMap<K, V>(comparator);
561     }
562 
563     /**
564      * Create and return a new instance of NavigableMap containing the same mappings as the specified
565      * map ordered according to the natural ordering of its keys.
566      *
567      * @param <K> key type
568      * @param <V> value type
569      * @param map map to copy mappings from, must not be null
570      * @return a new instance of NavigableMap containing the same mappings as the specified
571      *    map ordered according to the natural ordering of its keys
572      */
573     public static <K, V> NavigableMap<K, V> createNavigableMap(final Map<? extends K, ? extends V> map)
574     {
575         return new TreeMap<K, V>(map);
576     }
577 
578     /**
579      * Create and return a new instance of NavigableMap containing the same mappings and the same
580      * ordering as the specified navigable map.
581      *
582      * @param <K> key type
583      * @param <V> value type
584      * @param navigableMap navigable map to copy mappings and comparator from, must not be null
585      * @return a new instance of NavigableMap containing the same mappings and the same
586      *    ordering as the specified navigable map
587      */
588     public static <K, V> NavigableMap<K, V> createNavigableMap(final NavigableMap<K, ? extends V> navigableMap)
589     {
590         return new TreeMap<K, V>(navigableMap);
591     }
592 
593     /**
594      * Create and return a new unmodifiable view of the specified map.  Query operations on
595      * the returned map "read through" to the specified map.  Attempts to modify the returned map,
596      * whether direct or via its collection views, result in an <code>UnsupportedOperationException</code>.
597      *
598      * @param <K> key type
599      * @param <V> value type
600      * @param map map to view, must not be null
601      * @return a new unmodifiable view of the specified map
602      */
603     public static <K, V> Map<K, V> unmodifiableMap(final Map<? extends K, ? extends V> map)
604     {
605         return Collections.unmodifiableMap(map);
606     }
607 
608     /**
609      * Create and return a new unmodifiable view of the specified sorted map.  Query operations on
610      * the returned sorted map "read through" to the specified sorted map. Attempts to modify the
611      * returned sorted map, whether direct, via its collection views, or via its <code>subMap</code>,
612      * <code>headMap</code>, or <code>tailMap</code> views, result in an
613      * <code>UnsupportedOperationException</code>.
614      *
615      * @param <K> key type
616      * @param <V> value type
617      * @param sortedMap sorted map to view, must not be null
618      * @return a new unmodifiable view of the specified sorted map
619      */
620     public static <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> sortedMap)
621     {
622         return Collections.unmodifiableSortedMap(sortedMap);
623     }
624 
625     /**
626      * Create and return an immutable map containing the same mappings as the specified map.
627      *
628      * @param <K> key type
629      * @param <V> value type
630      * @param map map to copy, must not be null
631      * @return an immutable map containing the same mappings as the specified map
632      */
633     public static <K, V> Map<K, V> immutableMap(final Map<? extends K, ? extends V> map)
634     {
635         return ImmutableMap.copyOf(map);
636     }
637 
638     /**
639      * Create and return an immutable sorted map containing the same mappings and the same
640      * ordering as the specified sorted map.
641      *
642      * @param <K> key type
643      * @param <V> value type
644      * @param sortedMap sorted map to copy, must not be null
645      * @return an immutable sorted map containing the same mappings and the same
646      *    ordering as the specified sorted map
647      */
648     public static <K, V> SortedMap<K, V> immutableSortedMap(final SortedMap<K, ? extends V> sortedMap)
649     {
650         return ImmutableSortedMap.copyOfSorted(sortedMap);
651     }
652 }