com.google.common.collect.Maps Maven / Gradle / Ivy
Show all versions of google-collections Show documentation
/*
* Copyright (C) 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.base.Function;
import com.google.common.base.Nullable;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.MapConstraints.ConstrainedMap;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* Static utility methods pertaining to {@link Map} instances. Also see this
* class's counterparts {@link Lists} and {@link Sets}.
*
* @author Kevin Bourrillion
* @author Mike Bostock
*/
public final class Maps {
private Maps() {}
/**
* Creates a {@code HashMap} instance.
*
* Note: if {@code K} is an {@code enum} type, use {@link
* #newEnumMap} instead.
*
*
Note: if you don't actually need the resulting map to be mutable,
* use {@link Collections#emptyMap} instead.
*
* @return a newly-created, initially-empty {@code HashMap}
*/
public static HashMap newHashMap() {
return new HashMap();
}
/**
* Creates a {@code HashMap} instance with enough capacity to hold the
* specified number of elements without rehashing.
*
* @param expectedSize the expected size
* @return a newly-created {@code HashMap}, initially empty, with enough
* capacity to hold {@code expectedSize} elements without rehashing
* @throws IllegalArgumentException if {@code expectedSize} is negative
*/
public static HashMap newHashMapWithExpectedSize(
int expectedSize) {
/*
* The HashMap is constructed with an initialCapacity that's greater than
* expectedSize. The larger value is necessary because HashMap resizes
* its internal array if the map size exceeds loadFactor * initialCapacity.
*/
return new HashMap(capacity(expectedSize));
}
/**
* Returns an appropriate value for the "capacity" (in reality, "minimum
* table size") parameter of a {@link HashMap} constructor, such that the
* resulting table will be between 25% and 50% full when it contains
* {@code expectedSize} entries.
*
* @throws IllegalArgumentException if {@code expectedSize} is negative
*/
static int capacity(int expectedSize) {
checkArgument(expectedSize >= 0);
return Math.max(expectedSize * 2, 16);
}
/**
* Creates a {@code HashMap} instance with the same mappings as the specified
* map.
*
* Note: if {@code K} is an {@link Enum} type, use {@link
* #newEnumMap} instead.
*
* @param map the mappings to be placed in the new map
* @return a newly-created {@code HashMap} initialized with the mappings from
* {@code map}
*/
public static HashMap newHashMap(
Map extends K, ? extends V> map) {
return new HashMap(map);
}
/**
* Creates an insertion-ordered {@code LinkedHashMap} instance.
*
* @return a newly-created, initially-empty {@code LinkedHashMap}
*/
public static LinkedHashMap newLinkedHashMap() {
return new LinkedHashMap();
}
/**
* Creates an insertion-ordered {@code LinkedHashMap} instance with the same
* mappings as the specified map.
*
* @param map the mappings to be placed in the new map
* @return a newly-created, {@code LinkedHashMap} initialized with the
* mappings from {@code map}
*/
public static LinkedHashMap
newLinkedHashMap(Map extends K, ? extends V> map) {
return new LinkedHashMap(map);
}
/**
* Creates a {@code ConcurrentHashMap} instance.
*
* @return a newly-created, initially-empty {@code ConcurrentHashMap}
*/
public static ConcurrentHashMap newConcurrentHashMap() {
return new ConcurrentHashMap();
}
/**
* Creates a {@code TreeMap} instance using the natural ordering of its
* elements.
*
* @return a newly-created, initially-empty {@code TreeMap}
*/
@SuppressWarnings("unchecked") // allow ungenerified Comparable types
public static TreeMap newTreeMap() {
return new TreeMap();
}
/**
* Creates a {@code TreeMap} instance using the given comparator.
*
* @param comparator the comparator to sort the keys with
* @return a newly-created, initially-empty {@code TreeMap}
*/
public static TreeMap newTreeMap(
@Nullable Comparator comparator) {
// Ideally, the extra type parameter "C" shouldn't be necessary. It is a
// work-around of a compiler type inference quirk that prevents the
// following code from being compiled:
// Comparator> comparator = null;
// Map, String> map = newTreeMap(comparator);
return new TreeMap(comparator);
}
/**
* Creates an {@code EnumMap} instance.
*
* @param type the key type for this map
* @return a newly-created, initially-empty {@code EnumMap}
*/
public static , V> EnumMap newEnumMap(Class type) {
return new EnumMap(type);
}
/**
* Creates an {@code IdentityHashMap} instance.
*
* @return a newly-created, initially-empty {@code IdentityHashMap}
*/
public static IdentityHashMap newIdentityHashMap() {
return new IdentityHashMap();
}
/**
* Returns {@code true} if {@code map} contains an entry mapping {@code key}
* to {@code value}. If you are not concerned with null-safety you can simply
* use {@code map.get(key).equals(value)}.
*/
public static boolean containsEntry(
Map, ?> map, @Nullable Object key, @Nullable Object value) {
Object valueForKey = map.get(key);
return (valueForKey == null)
? value == null && map.containsKey(key)
: valueForKey.equals(value);
}
/**
* Returns a synchronized (thread-safe) bimap backed by the specified bimap.
* In order to guarantee serial access, it is critical that all access
* to the backing bimap is accomplished through the returned bimap.
*
* It is imperative that the user manually synchronize on the returned map
* when accessing any of its collection views:
*
*
Bimap<K,V> m = Maps.synchronizedBiMap(
* new HashBiMap<K,V>());
* ...
* Set<K> s = m.keySet(); // Needn't be in synchronized block
* ...
* synchronized (m) { // Synchronizing on m, not s!
* Iterator<K> i = s.iterator(); // Must be in synchronized block
* while (i.hasNext()) {
* foo(i.next());
* }
* }
*
* Failure to follow this advice may result in non-deterministic behavior.
*
* @param bimap the bimap to be wrapped in a synchronized view
* @return a sychronized view of the specified bimap
*/
public static BiMap synchronizedBiMap(BiMap bimap) {
return Synchronized.biMap(bimap, null);
}
/**
* Returns an immutable map for which the {@link Map#values} are the given
* elements in the given order, and each key is the product of invoking a
* supplied function on its corresponding value.
*
* @param values the values to use when constructing the {@code Map}
* @param keyFunction the function used to produce the key for each value
* @return a map mapping the result of evaluating the function {@code
* keyFunction} on each value in the input collection to that value
* @throws IllegalArgumentException if {@code keyFunction} produces the same
* key for more than one value in the input collection
* @throws NullPointerException if any elements of {@code values} is null, or
* if {@code keyFunction} produces {@code null} for any value
*/
// TODO: consider returning a bimap, whose inverse view does lookups by
// invoking the function.
public static ImmutableMap uniqueIndex(
Iterable values, Function super V, K> keyFunction) {
checkNotNull(keyFunction);
ImmutableMap.Builder builder = ImmutableMap.builder();
for (V value : values) {
builder.put(keyFunction.apply(value), value);
}
return builder.build();
}
/**
* Creates a {@code Map} from a {@code Properties} instance.
* Properties normally derive from {@code Map