Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2009 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 java.util.Map;
MapMaker emulation. Since Javascript is single-threaded and have no references, this reduces to the creation of expiring and computing maps.

Author(s):
Charles Fry
 
 public final class MapMaker extends GenericMapMaker<ObjectObject> {
 
   // TODO(fry,user): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
   // this implementation (based on a LHM) does. This will all be replaced soon anyways, so leaving
   // it as is for now.
   private static class ExpiringComputingMap<K, V> extends LinkedHashMap<K, V>
       implements ConcurrentMap<K, V> {
     private final long expirationMillis;
     private final Function<? super K, ? extends V> computer;
     private final int maximumSize;
 
         long expirationMillisint maximumSizeint initialCapacity) {
       this(expirationMillisnullmaximumSizeinitialCapacity);
     }
 
     ExpiringComputingMap(long expirationMillisFunction<? super K, ? extends V> computer,
         int maximumSizeint initialCapacity) {
       super(initialCapacity/* ignored loadFactor */ 0.75f, (maximumSize != -1));
       this. = expirationMillis;
       this. = computer;
       this. = maximumSize;
     }
 
     @Override
     public V put(K key, V value) {
       V result = super.put(keyvalue);
       if ( > 0) {
         scheduleRemoval(keyvalue);
       }
       return result;
     }
 
     @Override
     protected boolean removeEldestEntry(Map.Entry<K, V> ignored) {
       return ( == -1) ? false : size() > ;
     }
 
     @Override
     public V putIfAbsent(K key, V value) {
       if (!containsKey(key)) {
         return put(keyvalue);
       } else {
         return get(key);
       }
     }
 
     @Override
     public boolean remove(Object keyObject value) {
       if (containsKey(key) && get(key).equals(value)) {
         remove(key);
         return true;
       }
       return false;
     }
 
     @Override
     public boolean replace(K key, V oldValue, V newValue) {
       if (containsKey(key) && get(key).equals(oldValue)) {
         put(keynewValue);
         return true;
       }
       return false;
     }
 
     @Override
    public V replace(K key, V value) {
      return containsKey(key) ? put(keyvalue) : null;
    }
    private void scheduleRemoval(final K keyfinal V value) {
      // from MapMaker
      /*
       * TODO: Keep weak reference to map, too. Build a priority queue out of the entries themselves
       * instead of creating a task per entry. Then, we could have one recurring task per map (which
       * would clean the entire map and then reschedule itself depending upon when the next
       * expiration comes). We also want to avoid removing an entry prematurely if the entry was set
       * to the same value again.
       */
      Timer timer = new Timer() {
        @Override
        public void run() {
          remove(keyvalue);
        }
      };
      timer.schedule((int);
    }
    @Override
    public V get(Object k) {
      // from CustomConcurrentHashMap
      V result = super.get(k);
      if (result == null &&  != null) {
        /*
         * This cast isn't safe, but we can rely on the fact that K is almost always passed to
         * Map.get(), and tools like IDEs and Findbugs can catch situations where this isn't the
         * case.
         *
         * The alternative is to add an overloaded method, but the chances of a user calling get()
         * instead of the new API and the risks inherent in adding a new API outweigh this little
         * hole.
         */
        @SuppressWarnings("unchecked")
        K key = (K) k;
        result = compute(key);
      }
      return result;
    }
    private V compute(K key) {
      // from MapMaker
      V value;
      try {
        value = .apply(key);
      } catch (Throwable t) {
        throw new ComputationException(t);
      }
      if (value == null) {
        String message =  + " returned null for key " + key + ".";
        throw new NullPointerException(message);
      }
      put(keyvalue);
      return value;
    }
  }
  private int initialCapacity = 16;
  private long expirationMillis = 0;
  private int maximumSize = -1;
  private boolean useCustomMap;
  public MapMaker() {}
  public MapMaker initialCapacity(int initialCapacity) {
    if (initialCapacity < 0) {
      throw new IllegalArgumentException();
    }
    this. = initialCapacity;
    return this;
  }
  MapMaker expireAfterWrite(long durationTimeUnit unit) {
    if ( != 0) {
      throw new IllegalStateException(
          "expiration time of " +  + " ns was already set");
    }
    if (duration <= 0) {
      throw new IllegalArgumentException("invalid duration: " + duration);
    }
    this. = unit.toMillis(duration);
     = true;
    return this;
  }
  MapMaker maximumSize(int maximumSize) {
    if (this. != -1) {
      throw new IllegalStateException("maximum size of " + maximumSize + " was already set");
    }
    if (maximumSize < 0) {
      throw new IllegalArgumentException("invalid maximum size: " + maximumSize);
    }
    this. = maximumSize;
     = true;
    return this;
  }
  public MapMaker concurrencyLevel(int concurrencyLevel) {
    if (concurrencyLevel < 1) {
      throw new IllegalArgumentException("GWT only supports a concurrency level of 1");
    }
    // GWT technically only supports concurrencyLevel == 1, but we silently
    // ignore other positive values.
    return this;
  }
  public <K, V> ConcurrentMap<K, V> makeMap() {
    return 
        ? new ExpiringComputingMap<K, V>(null)
        : new ConcurrentHashMap<K, V>();
  }
  public <K, V> ConcurrentMap<K, V> makeComputingMap(Function<? super K, ? extends V> computer) {
    return new ExpiringComputingMap<K, V>(
        computer);
  }
New to GrepCode? Check out our FAQ X