package org.springside.modules.utils.collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumMap; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListMap; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableLong; import org.springside.modules.utils.base.Platforms; import org.springside.modules.utils.base.annotation.NotNull; import org.springside.modules.utils.base.annotation.Nullable; import org.springside.modules.utils.collection.type.primitive.IntObjectHashMap; import org.springside.modules.utils.collection.type.primitive.LongObjectHashMap; import org.springside.modules.utils.concurrent.jsr166e.ConcurrentHashMapV8; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ConcurrentHashMultiset; import com.google.common.collect.MapDifference; import com.google.common.collect.MapMaker; import com.google.common.collect.Maps; import com.google.common.collect.MultimapBuilder; import com.google.common.collect.SortedSetMultimap; import com.google.common.collect.TreeRangeMap; import com.google.common.util.concurrent.AtomicLongMap; /** * 关于Map的工具集合, * * 1. 常用函数(如是否为空) * * 2. 对于并发Map,增加putIfAbsent(返回最终值版), createIfAbsent这两个重要函数(from Common Lang) * * 3. 便捷的构造函数(via guava,Java Collections,并增加了用数组,List等方式初始化Map的函数) * * 4. 特殊的类型,包括WeakConcurrentHashMap, IntObjectHashMap, MapCounter, MultiKeyMap, RangeMap * * * 参考文章:《高性能场景下,Map家族的优化使用建议》 http://calvin1978.blogcn.com/articles/hashmap.html * * @author calvin */ @SuppressWarnings("unchecked") public class MapUtil { /** * 判断是否为空. */ public static boolean isEmpty(final Map<?, ?> map) { return (map == null) || map.isEmpty(); } /** * 判断是否为空. */ public static boolean isNotEmpty(final Map<?, ?> map) { return (map != null) && !map.isEmpty(); } /** * ConcurrentMap的putIfAbsent()返回之前的Value,此函数封装返回最终存储在Map中的Value * * @see org.apache.commons.lang3.concurrent.ConcurrentUtils#putIfAbsent(ConcurrentMap, Object, Object) */ public static <K, V> V putIfAbsentWithFinalValue(@NotNull final ConcurrentMap<K, V> map, final K key, final V value) { final V result = map.putIfAbsent(key, value); return result != null ? result : value; } /** * 如果Key不存在则创建,返回最后存储在Map中的Value. * * 如果创建对象有一定成本, 直接使用PutIfAbsent可能重复浪费,则使用此类,传入回调的ConcurrentInitializer * * @see org.apache.commons.lang3.concurrent.ConcurrentUtils#createIfAbsent(ConcurrentMap, Object, * org.apache.commons.lang3.concurrent.ConcurrentInitializer) */ public static <K, V> V createIfAbsent(@NotNull final ConcurrentMap<K, V> map, final K key, @NotNull final ValueCreator<? extends V> creator) { final V value = map.get(key); if (value == null) { return putIfAbsentWithFinalValue(map, key, creator.get()); } return value; } /** * 创建Value值的回调函数 * * @see MapUtil#createIfAbsent(ConcurrentMap, Object, ValueCreator) */ public interface ValueCreator<T> { /** * 创建对象 */ T get(); } ///////////////// from Guava的构造函数/////////////////// /** * 根据等号左边的类型, 构造类型正确的HashMap. * * 未初始化数组大小, 默认为16个桶. * * @see com.google.common.collect.Maps#newHashMap() */ public static <K, V> HashMap<K, V> newHashMap() { return new HashMap<K, V>(); } /** * 根据等号左边的类型, 构造类型正确的HashMap. * * 注意HashMap中有0.75的加载因子的影响, 需要进行运算后才能正确初始化HashMap的大小. * * 加载因子也是HashMap中减少Hash冲突的重要一环,如果读写频繁,总记录数不多的Map,可以比默认值0.75进一步降低,建议0.5 * * @see com.google.common.collect.Maps#newHashMap(int) */ public static <K, V> HashMap<K, V> newHashMapWithCapacity(int expectedSize, float loadFactor) { int finalSize = (int) ((double) expectedSize / loadFactor + 1.0F); return new HashMap<K, V>(finalSize, loadFactor); } /** * 根据等号左边的类型, 构造类型正确的HashMap. * * 同时初始化第一个元素 */ public static <K, V> HashMap<K, V> newHashMap(final K key, final V value) { HashMap<K, V> map = new HashMap<K, V>(); map.put(key, value); return map; } /** * 根据等号左边的类型, 构造类型正确的HashMap. * * 同时初始化元素. */ public static <K, V> HashMap<K, V> newHashMap(@NotNull final K[] keys, @NotNull final V[] values) { if (keys.length != values.length) { throw new IllegalArgumentException( "keys.length is " + keys.length + " but values.length is " + values.length); } HashMap<K, V> map = new HashMap<K, V>(); for (int i = 0; i < keys.length; i++) { map.put(keys[i], values[i]); } return map; } /** * 根据等号左边的类型, 构造类型正确的HashMap. * * 同时初始化元素. */ public static <K, V> HashMap<K, V> newHashMap(@NotNull final List<K> keys, @NotNull final List<V> values) { if (keys.size() != values.size()) { throw new IllegalArgumentException("keys.size is " + keys.size() + " but values.size is " + values.size()); } HashMap<K, V> map = new HashMap<K, V>(); Iterator<K> keyIt = keys.iterator(); Iterator<V> valueIt = values.iterator(); while (keyIt.hasNext()) { map.put(keyIt.next(), valueIt.next()); } return map; } /** * 根据等号左边的类型,构造类型正确的TreeMap. * * @see com.google.common.collect.Maps#newTreeMap() */ @SuppressWarnings("rawtypes") public static <K extends Comparable, V> TreeMap<K, V> newSortedMap() { return new TreeMap<K, V>(); } /** * 根据等号左边的类型,构造类型正确的TreeMap. * * @see com.google.common.collect.Maps#newTreeMap(Comparator) */ public static <C, K extends C, V> TreeMap<K, V> newSortedMap(@Nullable Comparator<C> comparator) { return Maps.newTreeMap(comparator); } /** * 相比HashMap,当key是枚举类时, 性能与空间占用俱佳. */ public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(@NotNull Class<K> type) { return new EnumMap<K, V>(Preconditions.checkNotNull(type)); } /** * JDK8下,ConcurrentHashMap已不再需要设置loadFactor, concurrencyLevel和initialCapacity. * * 如果JDK8,使用原生ConcurrentHashMap,否则使用移植版 */ public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap() { if (Platforms.IS_ATLEASET_JAVA8) { return new ConcurrentHashMap<K, V>(); } else { return new ConcurrentHashMapV8<K, V>(); } } /** * 根据等号左边的类型,构造类型正确的ConcurrentSkipListMap. */ public static <K, V> ConcurrentSkipListMap<K, V> newConcurrentSortedMap() { return new ConcurrentSkipListMap<K, V>(); } ///////////////// from Guava的特别Map ////////////////////// /** * 创建Key为弱引用的ConcurrentMap,Key对象可被回收. * * JDK没有WeakHashMap的并发实现, 由Guava提供 */ public static <K, V> ConcurrentMap<K, V> createWeakKeyConcurrentHashMap(int initialCapacity, int concurrencyLevel) { return new MapMaker().weakKeys().initialCapacity(initialCapacity).concurrencyLevel(concurrencyLevel).makeMap(); } /** * 创建Value为弱引用的ConcurrentMap,Value对象可被回收. * * JDK没有WeakHashMap的并发实现, 由Guava提供 */ public static <K, V> ConcurrentMap<K, V> createWeakValueConcurrentHashMap(int initialCapacity, int concurrencyLevel) { return new MapMaker().weakValues().initialCapacity(initialCapacity).concurrencyLevel(concurrencyLevel) .makeMap(); } /** * 创建移植自Netty的key为int的优化HashMap * * @param initialCapacity 建议为16 * @param loadFactor 建议为0.5 */ public static <V> IntObjectHashMap<V> createIntObjectHashMap(int initialCapacity, float loadFactor) { return new IntObjectHashMap<V>(initialCapacity, loadFactor); } /** * 创建移植自Netty的key为long的优化HashMap * * @param initialCapacity 建议为16 * @param loadFactor 建议为0.5 */ public static <V> LongObjectHashMap<V> createLongObjectHashMap(int initialCapacity, float loadFactor) { return new LongObjectHashMap<V>(initialCapacity, loadFactor); } /** * 创建值为可更改的Integer的HashMap. 可更改的Integer在更改时不需要重新创建Integer对象,节约了内存 * * @param initialCapacity 建议为16 * @param loadFactor 建议为0.5 */ public static <K> HashMap<K, MutableInt> createMutableIntValueHashMap(int initialCapacity, float loadFactor) { return new HashMap<K, MutableInt>(initialCapacity, loadFactor); } /** * 创建值为可更改的Long的HashMap. 可更改的Long在更改时不需要重新创建Long对象,节约了内存 * * @param initialCapacity 建议为16 * @param loadFactor 建议为0.5 */ public static <K> HashMap<K, MutableLong> createMutableLongValueHashMap(int initialCapacity, float loadFactor) { return new HashMap<K, MutableLong>(initialCapacity, loadFactor); } /** * 以Guava的AtomicLongMap,实现线程安全的HashMap<E,AtomicLong>结构的Counter */ public static <E> AtomicLongMap<E> createConcurrentMapCounter() { return AtomicLongMap.create(); } /** * 以Guava的MultiSet,实现线程安全的HashMap<E,Integer>结构的Counter */ public static <E> ConcurrentHashMultiset<E> createConcurrentMapCounter(Iterable<? extends E> elements) { return ConcurrentHashMultiset.create(elements); } /** * 以Guava的MultiMap,实现的HashMap<E,List<V>>结构的一个Key对应多个值的map. * * 注意非线程安全, MultiMap无线程安全的实现. * * 另有其他结构存储values的MultiMap,请自行参考MultimapBuilder使用. * * @param expectedKeys 默认为16 * @param expectedValuesPerKey 默认为3 */ public static <K, V> ArrayListMultimap<K, V> createListValueMap(int expectedKeys, int expectedValuesPerKey) { return ArrayListMultimap.create(expectedKeys, expectedValuesPerKey); } /** * 以Guava的MultiMap,实现的HashMap<E,TreeSet<V>>结构的一个Key对应多个值的map. * * 注意非线程安全, MultiMap无线程安全的实现. * * 另有其他结构存储values的MultiMap,请自行参考MultimapBuilder使用. */ public static <K, V extends Comparable> SortedSetMultimap<K, V> createSortedSetValueMap() { return MultimapBuilder.hashKeys().treeSetValues().build(); } /** * 以Guava的MultiMap,实现的HashMap<E,TreeSet<V>>结构的一个Key对应多个值的map. * * 注意非线程安全, MultiMap无线程安全的实现. * * 另有其他结构存储values的MultiMap,请自行参考MultimapBuilder使用. */ public static <K, V> SortedSetMultimap<K, V> createSortedSetValueMap(Comparator<V> comparator) { return (SortedSetMultimap<K, V>) MultimapBuilder.hashKeys().treeSetValues(comparator); } /** * 以Guava TreeRangeMap实现的, 一段范围的Key指向同一个Value的Map */ @SuppressWarnings("rawtypes") public static <K extends Comparable, V> TreeRangeMap<K, V> createRangeMap() { return TreeRangeMap.create(); } ///////////////// from JDK Collections的常用构造函数 /////////////////// /** * 返回一个空的结构特殊的Map,节约空间. * * 注意返回的Map不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#emptyMap() */ public static final <K, V> Map<K, V> emptyMap() { return (Map<K, V>) Collections.EMPTY_MAP; } /** * 如果map为null,转化为一个安全的空Map. * * 注意返回的Map不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#emptyMap() */ public static <K, V> Map<K, V> emptyMapIfNull(final Map<K, V> map) { return map == null ? (Map<K, V>) Collections.EMPTY_MAP : map; } /** * 返回一个只含一个元素但结构特殊的Map,节约空间. * * 注意返回的Map不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#singletonMap(Object, Object) */ public static <K, V> Map<K, V> singletonMap(final K key, final V value) { return Collections.singletonMap(key, value); } /** * 返回包装后不可修改的Map. * * 如果尝试修改,会抛出UnsupportedOperationException * * @see java.util.Collections#unmodifiableMap(Map) */ public static <K, V> Map<K, V> unmodifiableMap(final Map<? extends K, ? extends V> m) { return Collections.unmodifiableMap(m); } /** * 返回包装后不可修改的有序Map. * * @see java.util.Collections#unmodifiableSortedMap(SortedMap) */ public static <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> m) { return Collections.unmodifiableSortedMap(m); } //////// Map的集合操作 ////// /** * 对两个Map进行比较,返回MapDifference,然后各种妙用. * * 包括key的差集,key的交集,以及key相同但value不同的元素。 */ public static <K, V> MapDifference<K, V> difference(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) { return Maps.difference(left, right); } }