// ================================================================================================= // Copyright 2011 Twitter, Inc. // ------------------------------------------------------------------------------------------------- // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this work except in compliance with the License. // You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.stats; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.logging.Logger; /** * A map from a key type to integers. This simplifies the process of storing counters for multiple * values of the same type. */ public class CounterMap <K> implements Iterable<Map.Entry<K, Integer>>, Cloneable { private final Map<K, Integer> map = Maps.newHashMap(); private static Logger log = Logger.getLogger(CounterMap.class.getName()); /** * Increments the counter value associated with {@code key}, and returns the new value. * * @param key The key to increment * @return The incremented value. */ public int incrementAndGet(K key) { return incrementAndGet(key, 1); } /** * Increments the value associated with {@code key} by {@code value}, returning the new value. * * @param key The key to increment * @return The incremented value. */ public int incrementAndGet(K key, int count) { Integer value = map.get(key); if (value == null) { value = 0; } int newValue = count + value; map.put(key, newValue); return newValue; } /** * Gets the value associated with a key. * * @param key The key to look up. * @return The counter value stored for {@code key}, or 0 if no mapping exists. */ public int get(K key) { if (!map.containsKey(key)) { return 0; } return map.get(key); } /** * Assigns a value to a key. * * @param key The key to assign a value to. * @param newValue The value to assign. */ public void set(K key, int newValue) { Preconditions.checkNotNull(key); map.put(key, newValue); } /** * Resets the value for {@code key}. This will remove the key from the counter. * * @param key The key to reset. */ public void reset(K key) { map.remove(key); } /** * Gets the number of entries stored in the map. * * @return The size of the map. */ public int size() { return map.size(); } /** * Gets an iterator for the mapped values. * * @return Iterator for mapped values. */ public Iterator<Map.Entry<K, Integer>> iterator() { return map.entrySet().iterator(); } public Collection<Integer> values() { return map.values(); } public Set<K> keySet() { return map.keySet(); } public String toString() { StringBuilder strVal = new StringBuilder(); for (Map.Entry<K, Integer> entry : this) { strVal.append(entry.getKey().toString()).append(": ").append(entry.getValue()).append('\n'); } return strVal.toString(); } public Map<K, Integer> toMap() { return map; } @Override public CounterMap<K> clone() { CounterMap<K> newInstance = new CounterMap<K>(); newInstance.map.putAll(map); return newInstance; } }