Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2008 The Guava Authors
   *
   * 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 static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.getOnlyElement;
 
 
 import java.util.List;
 import java.util.Map;
 
An immutable, hash-based java.util.Map with reliable user-specified iteration order. Does not permit null keys or values.

Unlike java.util.Collections.unmodifiableMap(java.util.Map), which is a view of a separate map which can still change, an instance of ImmutableMap contains its own data and will never change. ImmutableMap is convenient for public static final maps ("constant maps") and also lets you easily make a "defensive copy" of a map provided to your class by a caller.

Performance notes: unlike java.util.HashMap, ImmutableMap is not optimized for element types that have slow java.lang.Object.equals(java.lang.Object) or java.lang.Object.hashCode() implementations. You can get better performance by having your element type cache its own hash codes, and by making use of the cached values to short-circuit a slow equals algorithm.

See the Guava User Guide article on immutable collections.

Author(s):
Jesse Wilson
Kevin Bourrillion
Since:
2.0 (imported from Google Collections Library)
 
 @GwtCompatible(serializable = true, emulated = true)
 @SuppressWarnings("serial"// we're overriding default serialization
 public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
  
Returns the empty map. This map behaves and performs comparably to java.util.Collections.emptyMap(), and is preferable mainly for consistency and maintainability of your code.
 
   // Casting to any type is safe because the set will never hold any elements.
   @SuppressWarnings("unchecked")
   public static <K, V> ImmutableMap<K, V> of() {
     return (ImmutableMap<K, V>) .;
   }

  
Returns an immutable map containing a single entry. This map behaves and performs comparably to java.util.Collections.singletonMap(java.lang.Object,java.lang.Object) but will not accept a null key or value. It is preferable mainly for consistency and maintainability of your code.
 
   public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {
     return new SingletonImmutableMap<K, V>(
         checkNotNull(k1), checkNotNull(v1));
   }

  
Returns an immutable map containing the given entries, in order.

Throws:
java.lang.IllegalArgumentException if duplicate keys are provided
 
   public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
     return new RegularImmutableMap<K, V>(entryOf(k1v1), entryOf(k2v2));
   }

  
Returns an immutable map containing the given entries, in order.

Throws:
java.lang.IllegalArgumentException if duplicate keys are provided
 
   public static <K, V> ImmutableMap<K, V> of(
       K k1, V v1, K k2, V v2, K k3, V v3) {
    return new RegularImmutableMap<K, V>(
        entryOf(k1v1), entryOf(k2v2), entryOf(k3v3));
  }

  
Returns an immutable map containing the given entries, in order.

Throws:
java.lang.IllegalArgumentException if duplicate keys are provided
  public static <K, V> ImmutableMap<K, V> of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
    return new RegularImmutableMap<K, V>(
        entryOf(k1v1), entryOf(k2v2), entryOf(k3v3), entryOf(k4v4));
  }

  
Returns an immutable map containing the given entries, in order.

Throws:
java.lang.IllegalArgumentException if duplicate keys are provided
  public static <K, V> ImmutableMap<K, V> of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
    return new RegularImmutableMap<K, V>(entryOf(k1v1),
        entryOf(k2v2), entryOf(k3v3), entryOf(k4v4), entryOf(k5v5));
  }
  // looking for of() with > 5 entries? Use the builder instead.

  
Returns a new builder. The generated builder is equivalent to the builder created by the ImmutableMap.Builder constructor.
  public static <K, V> Builder<K, V> builder() {
    return new Builder<K, V>();
  }

  
Verifies that key and value are non-null, and returns a new immutable entry with those values.

A call to java.util.Map.Entry.setValue(java.lang.Object) on the returned entry will always throw java.lang.UnsupportedOperationException.

  static <K, V> Entry<K, V> entryOf(K key, V value) {
    return Maps.immutableEntry(
        checkNotNull(key"null key"),
        checkNotNull(value"null value"));
  }

  
A builder for creating immutable map instances, especially public static final maps ("constant maps"). Example:
   static final ImmutableMap<String, Integer> WORD_TO_INT =
       new ImmutableMap.Builder<String, Integer>()
           .put("one", 1)
           .put("two", 2)
           .put("three", 3)
           .build();
For small immutable maps, the ImmutableMap.of() methods are even more convenient.

Builder instances can be reused - it is safe to call build() multiple times to build multiple maps in series. Each map is a superset of the maps created before it.

Since:
2.0 (imported from Google Collections Library)
  public static class Builder<K, V> {
    final ArrayList<Entry<K, V>> entries = Lists.newArrayList();

    
Creates a new builder. The returned builder is equivalent to the builder generated by ImmutableMap.builder().
    public Builder() {}

    
Associates key with value in the built map. Duplicate keys are not allowed, and will cause build() to fail.
    public Builder<K, V> put(K key, V value) {
      .add(entryOf(keyvalue));
      return this;
    }

    
Adds the given entry to the map, making it immutable if necessary. Duplicate keys are not allowed, and will cause build() to fail.

Since:
11.0
    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
      K key = entry.getKey();
      V value = entry.getValue();
      if (entry instanceof ImmutableEntry<?, ?>) {
        checkNotNull(key);
        checkNotNull(value);
        @SuppressWarnings("unchecked"// all supported methods are covariant
        Entry<K, V> immutableEntry = (Entry<K, V>) entry;
        .add(immutableEntry);
      } else {
        // Directly calling entryOf(entry.getKey(), entry.getValue()) can cause
        // compilation error in Eclipse.
        .add(entryOf(keyvalue));
      }
      return this;
    }

    
Associates all of the given map's keys and values in the built map. Duplicate keys are not allowed, and will cause build() to fail.

Throws:
java.lang.NullPointerException if any key or value in map is null
    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
      .ensureCapacity(.size() + map.size());
      for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
        put(entry.getKey(), entry.getValue());
      }
      return this;
    }
    /*
     * TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap
     * versions throw an IllegalStateException instead?
     */

    
Returns a newly-created immutable map.

Throws:
java.lang.IllegalArgumentException if duplicate keys were added
    public ImmutableMap<K, V> build() {
      return fromEntryList();
    }
    private static <K, V> ImmutableMap<K, V> fromEntryList(
        List<Entry<K, V>> entries) {
      int size = entries.size();
      switch (size) {
        case 0:
          return of();
        case 1:
          return new SingletonImmutableMap<K, V>(getOnlyElement(entries));
        default:
          Entry<?, ?>[] entryArray
              = entries.toArray(new Entry<?, ?>[entries.size()]);
          return new RegularImmutableMap<K, V>(entryArray);
      }
    }
  }

  
Returns an immutable map containing the same entries as map. If map somehow contains entries with duplicate keys (for example, if it is a SortedMap whose comparator is not consistent with equals), the results of this method are undefined.

Despite the method name, this method attempts to avoid actually copying the data when it is safe to do so. The exact circumstances under which a copy will or will not be performed are undocumented and subject to change.

Throws:
java.lang.NullPointerException if any key or value in map is null
  public static <K, V> ImmutableMap<K, V> copyOf(
      Map<? extends K, ? extends V> map) {
    if ((map instanceof ImmutableMap) && !(map instanceof ImmutableSortedMap)) {
      // TODO(user): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
      // on the ImmutableMap delegate(), rather than the bimap itself
      @SuppressWarnings("unchecked"// safe since map is not writable
      ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) map;
      if (!kvMap.isPartialView()) {
        return kvMap;
      }
    }
    @SuppressWarnings("unchecked"// we won't write to this array
    Entry<K, V>[] entries = map.entrySet().toArray(new Entry[0]);
    switch (entries.length) {
      case 0:
        return of();
      case 1:
        return new SingletonImmutableMap<K, V>(entryOf(
            entries[0].getKey(), entries[0].getValue()));
      default:
        for (int i = 0; i < entries.lengthi++) {
          K k = entries[i].getKey();
          V v = entries[i].getValue();
          entries[i] = entryOf(kv);
        }
        return new RegularImmutableMap<K, V>(entries);
    }
  }
  ImmutableMap() {}

  
Guaranteed to throw an exception and leave the map unmodified.

  public final V put(K k, V v) {
    throw new UnsupportedOperationException();
  }

  
Guaranteed to throw an exception and leave the map unmodified.

  public final V remove(Object o) {
    throw new UnsupportedOperationException();
  }

  
Guaranteed to throw an exception and leave the map unmodified.

  public final void putAll(Map<? extends K, ? extends V> map) {
    throw new UnsupportedOperationException();
  }

  
Guaranteed to throw an exception and leave the map unmodified.

  public final void clear() {
    throw new UnsupportedOperationException();
  }
  public boolean isEmpty() {
    return size() == 0;
  }
  public boolean containsKey(@Nullable Object key) {
    return get(key) != null;
  }
  // Overriding to mark it Nullable
  public abstract boolean containsValue(@Nullable Object value);
  // Overriding to mark it Nullable
  public abstract V get(@Nullable Object key);
  private transient ImmutableSet<Entry<K, V>> entrySet;

  
Returns an immutable set of the mappings in this map. The entries are in the same order as the parameters used to build this map.
  public ImmutableSet<Entry<K, V>> entrySet() {
    ImmutableSet<Entry<K, V>> result = ;
    return (result == null) ?  = createEntrySet() : result;
  }
  abstract ImmutableSet<Entry<K, V>> createEntrySet();
  abstract class EntrySet extends ImmutableSet<Entry<K, V>> {
    @Override
    public int size() {
      return ImmutableMap.this.size();
    }
    @Override
    public boolean contains(@Nullable Object object) {
      if (object instanceof Entry) {
        Entry<?, ?> entry = (Entry<?, ?>) object;
        V value = get(entry.getKey());
        return value != null && value.equals(entry.getValue());
      }
      return false;
    }
    @Override
    boolean isPartialView() {
      return ImmutableMap.this.isPartialView();
    }
    @Override
    Object writeReplace() {
      return new EntrySetSerializedForm<K, V>(ImmutableMap.this);
    }
  }
  private static class EntrySetSerializedForm<K, V> implements Serializable {
    final ImmutableMap<K, V> map;
    EntrySetSerializedForm(ImmutableMap<K, V> map) {
      this. = map;
    }
    Object readResolve() {
      return .entrySet();
    }
    private static final long serialVersionUID = 0;
  }
  private transient ImmutableSet<K> keySet;

  
Returns an immutable set of the keys in this map. These keys are in the same order as the parameters used to build this map.
  public ImmutableSet<K> keySet() {
    ImmutableSet<K> result = ;
    return (result == null) ?  = createKeySet() : result;
  }
    return new KeySet();
  }
  class KeySet extends TransformedImmutableSet<Entry<K, V>, K> {
    KeySet() {
      super(entrySet());
    }
    KeySet(int hashCode) {
      super(entrySet(), hashCode);
    }
    @Override
    K transform(Entry<K, V> entry) {
      return entry.getKey();
    }
    @Override
    public boolean contains(@Nullable Object object) {
      return containsKey(object);
    }
    @Override
    boolean isPartialView() {
      return true;
    }
    @Override
      // TODO(user): rewrite to delegate contains() calls to the KeySet
      return new TransformedImmutableList<Entry<K, V>, K>(entrySet().asList()) {
        @Override
        K transform(Entry<K, V> entry) {
          return entry.getKey();
        }
      };
    }
      return new KeySetSerializedForm<K>(ImmutableMap.this);
    }
  }
  private static class KeySetSerializedForm<K> implements Serializable {
    final ImmutableMap<K, ?> map;
    KeySetSerializedForm(ImmutableMap<K, ?> map) {
      this. = map;
    }
    Object readResolve() {
      return .keySet();
    }
    private static final long serialVersionUID = 0;
  }
  private transient ImmutableCollection<V> values;

  
Returns an immutable collection of the values in this map. The values are in the same order as the parameters used to build this map.
  public ImmutableCollection<V> values() {
    ImmutableCollection<V> result = ;
    return (result == null) ?  = createValues() : result;
  }
    return new Values();
  }
  class Values extends ImmutableCollection<V> {
    @Override
    public int size() {
      return ImmutableMap.this.size();
    }
    @Override
    public UnmodifiableIterator<V> iterator() {
      return Maps.valueIterator(entrySet().iterator());
    }
    @Override
    public boolean contains(Object object) {
      return containsValue(object);
    }
    @Override
    boolean isPartialView() {
      return true;
    }
    @Override
      // TODO(user): rewrite to delegate contains() calls to the Values
      return new TransformedImmutableList<Entry<K, V>, V>(entrySet().asList()) {
        @Override
        V transform(Entry<K, V> entry) {
          return entry.getValue();
        }
      };
    }
      return new ValuesSerializedForm<V>(ImmutableMap.this);
    }
  }
  private static class ValuesSerializedForm<V> implements Serializable {
    final ImmutableMap<?, V> map;
    ValuesSerializedForm(ImmutableMap<?, V> map) {
      this. = map;
    }
    Object readResolve() {
      return .values();
    }
    private static final long serialVersionUID = 0;
  }
  @Override public boolean equals(@Nullable Object object) {
    if (object == this) {
      return true;
    }
    if (object instanceof Map) {
      Map<?, ?> that = (Map<?, ?>) object;
      return this.entrySet().equals(that.entrySet());
    }
    return false;
  }
  abstract boolean isPartialView();
  @Override public int hashCode() {
    // not caching hash code since it could change if map values are mutable
    // in a way that modifies their hash codes
    return entrySet().hashCode();
  }
  @Override public String toString() {
    return Maps.toStringImpl(this);
  }

  
Serialized type for all ImmutableMap instances. It captures the logical contents and they are reconstructed using public factory methods. This ensures that the implementation types remain as implementation details.
  static class SerializedForm implements Serializable {
    private final Object[] keys;
    private final Object[] values;
    SerializedForm(ImmutableMap<?, ?> map) {
       = new Object[map.size()];
       = new Object[map.size()];
      int i = 0;
      for (Entry<?, ?> entry : map.entrySet()) {
        [i] = entry.getKey();
        [i] = entry.getValue();
        i++;
      }
    }
    Object readResolve() {
      Builder<ObjectObjectbuilder = new Builder<ObjectObject>();
      return createMap(builder);
    }
    Object createMap(Builder<ObjectObjectbuilder) {
      for (int i = 0; i < .i++) {
        builder.put([i], [i]);
      }
      return builder.build();
    }
    private static final long serialVersionUID = 0;
  }
    return new SerializedForm(this);
  }
New to GrepCode? Check out our FAQ X