Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Joiner.MapJoiner;
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.base.Predicate;
import com.google.common.base.Predicates;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
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.SortedMap;
import java.util.TreeMap;
import javax.annotation.Nullable;
/**
* 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
* @author Isaac Shum
*/
@GwtCompatible
public final class Maps {
private Maps() {}
/**
* Creates a mutable, empty {@code HashMap} instance.
*
*
Note: if mutability is not required, use {@link
* ImmutableMap#of()} instead.
*
*
Note: if {@code K} is an {@code enum} type, use {@link
* #newEnumMap} instead.
*
* @return a new, 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 new, empty {@code HashMap} 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 mutable {@code HashMap} instance with the same mappings as
* the specified map.
*
*
Note: if mutability is not required, use {@link
* ImmutableMap#copyOf(Map)} instead.
*
*
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 new {@code HashMap} initialized with the mappings from
* {@code map}
*/
public static HashMap newHashMap(
Map extends K, ? extends V> map) {
return new HashMap(map);
}
/**
* Creates a mutable, empty, insertion-ordered {@code LinkedHashMap}
* instance.
*
*
Note: if mutability is not required, use {@link
* ImmutableMap#of()} instead.
*
* @return a new, empty {@code LinkedHashMap}
*/
public static LinkedHashMap newLinkedHashMap() {
return new LinkedHashMap();
}
/**
* Creates a mutable, insertion-ordered {@code LinkedHashMap} instance
* with the same mappings as the specified map.
*
*
Note: if mutability is not required, use {@link
* ImmutableMap#copyOf(Map)} instead.
*
* @param map the mappings to be placed in the new map
* @return a new, {@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 mutable, empty {@code TreeMap} instance using the natural
* ordering of its elements.
*
*
Note: if mutability is not required, use {@link
* ImmutableSortedMap#of()} instead.
*
* @return a new, empty {@code TreeMap}
*/
@SuppressWarnings("unchecked") // eclipse doesn't like the raw Comparable
public static TreeMap newTreeMap() {
return new TreeMap();
}
/**
* Creates a mutable {@code TreeMap} instance with the same mappings as
* the specified map and using the same ordering as the specified map.
*
*
Note: if mutability is not required, use {@link
* ImmutableSortedMap#copyOfSorted(SortedMap)} instead.
*
* @param map the sorted map whose mappings are to be placed in the new map
* and whose comparator is to be used to sort the new map
* @return a new {@code TreeMap} initialized with the mappings from {@code
* map} and using the comparator of {@code map}
*/
public static TreeMap newTreeMap(SortedMap map) {
return new TreeMap(map);
}
/**
* Creates a mutable, empty {@code TreeMap} instance using the given
* comparator.
*
*
Note: if mutability is not required, use {@code
* ImmutableSortedMap.orderedBy(comparator).build()} instead.
*
* @param comparator the comparator to sort the keys with
* @return a new, 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 new, empty {@code EnumMap}
*/
public static , V> EnumMap newEnumMap(Class type) {
return new EnumMap(checkNotNull(type));
}
/**
* Creates an {@code EnumMap} with the same mappings as the specified map.
*
* @param map the map from which to initialize this {@code EnumMap}
* @return a new {@code EnumMap} initialized with the mappings from {@code
* map}
* @throws IllegalArgumentException if {@code m} is not an {@code EnumMap}
* instance and contains no mappings
*/
public static , V> EnumMap newEnumMap(
Map map) {
return new EnumMap(map);
}
/**
* Creates an {@code IdentityHashMap} instance.
*
* @return a new, empty {@code IdentityHashMap}
*/
public static IdentityHashMap newIdentityHashMap() {
return new IdentityHashMap();
}
/**
* 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:
{@code
*
* BiMap map = Maps.synchronizedBiMap(
* HashBiMap.create());
* ...
* Set set = map.keySet(); // Needn't be in synchronized block
* ...
* synchronized (map) { // Synchronizing on map, not set!
* Iterator it = set.iterator(); // Must be in synchronized block
* while (it.hasNext()) {
* foo(it.next());
* }
* }}
*
* Failure to follow this advice may result in non-deterministic behavior.
*
*
The returned bimap will be serializable if the specified bimap is
* serializable.
*
* @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);
}
/**
* Computes the difference between two maps. This difference is an immutable
* snapshot of the state of the maps at the time this method is called. It
* will never change, even if the maps change at a later time.
*
*
Since this method uses {@code HashMap} instances internally, the keys of
* the supplied maps must be well-behaved with respect to
* {@link Object#equals} and {@link Object#hashCode}.
*
*
Note:If you only need to know whether two maps have the same
* mappings, call {@code left.equals(right)} instead of this method.
*
* @param left the map to treat as the "left" map for purposes of comparison
* @param right the map to treat as the "right" map for purposes of comparison
* @return the difference between the two maps
*/
public static MapDifference difference(
Map extends K, ? extends V> left, Map extends K, ? extends V> right) {
Map onlyOnLeft = newHashMap();
Map onlyOnRight = new HashMap(right); // will whittle it down
Map onBoth = newHashMap();
Map> differences = newHashMap();
boolean eq = true;
for (Entry extends K, ? extends V> entry : left.entrySet()) {
K leftKey = entry.getKey();
V leftValue = entry.getValue();
if (right.containsKey(leftKey)) {
V rightValue = onlyOnRight.remove(leftKey);
if (Objects.equal(leftValue, rightValue)) {
onBoth.put(leftKey, leftValue);
} else {
eq = false;
differences.put(leftKey, new ValueDifferenceImpl(
leftValue, rightValue));
}
} else {
eq = false;
onlyOnLeft.put(leftKey, leftValue);
}
}
boolean areEqual = eq && onlyOnRight.isEmpty();
return new MapDifferenceImpl(
areEqual, onlyOnLeft, onlyOnRight, onBoth, differences);
}
private static class MapDifferenceImpl
implements MapDifference {
final boolean areEqual;
final Map onlyOnLeft;
final Map onlyOnRight;
final Map onBoth;
final Map> differences;
MapDifferenceImpl(boolean areEqual, Map onlyOnLeft,
Map onlyOnRight, Map onBoth,
Map> differences) {
this.areEqual = areEqual;
this.onlyOnLeft = Collections.unmodifiableMap(onlyOnLeft);
this.onlyOnRight = Collections.unmodifiableMap(onlyOnRight);
this.onBoth = Collections.unmodifiableMap(onBoth);
this.differences = Collections.unmodifiableMap(differences);
}
public boolean areEqual() {
return areEqual;
}
public Map entriesOnlyOnLeft() {
return onlyOnLeft;
}
public Map entriesOnlyOnRight() {
return onlyOnRight;
}
public Map entriesInCommon() {
return onBoth;
}
public Map> entriesDiffering() {
return differences;
}
@Override public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof MapDifference) {
MapDifference, ?> other = (MapDifference, ?>) object;
return entriesOnlyOnLeft().equals(other.entriesOnlyOnLeft())
&& entriesOnlyOnRight().equals(other.entriesOnlyOnRight())
&& entriesInCommon().equals(other.entriesInCommon())
&& entriesDiffering().equals(other.entriesDiffering());
}
return false;
}
@Override public int hashCode() {
return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(),
entriesInCommon(), entriesDiffering());
}
@Override public String toString() {
if (areEqual) {
return "equal";
}
StringBuilder result = new StringBuilder("not equal");
if (!onlyOnLeft.isEmpty()) {
result.append(": only on left=").append(onlyOnLeft);
}
if (!onlyOnRight.isEmpty()) {
result.append(": only on right=").append(onlyOnRight);
}
if (!differences.isEmpty()) {
result.append(": value differences=").append(differences);
}
return result.toString();
}
}
static class ValueDifferenceImpl
implements MapDifference.ValueDifference {
private final V left;
private final V right;
ValueDifferenceImpl(@Nullable V left, @Nullable V right) {
this.left = left;
this.right = right;
}
public V leftValue() {
return left;
}
public V rightValue() {
return right;
}
@Override public boolean equals(@Nullable Object object) {
if (object instanceof MapDifference.ValueDifference>) {
MapDifference.ValueDifference> that =
(MapDifference.ValueDifference>) object;
return Objects.equal(this.left, that.leftValue())
&& Objects.equal(this.right, that.rightValue());
}
return false;
}
@Override public int hashCode() {
return Objects.hashCode(left, right);
}
@Override public String toString() {
return "(" + left + ", " + right + ")";
}
}
/**
* 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 an {@code ImmutableMap} from a {@code Properties}
* instance. Properties normally derive from {@code Map