1 /* 2 StatCvs - CVS statistics generation 3 Copyright (C) 2002 Lukasz Pekacki <lukasz@pekacki.de> 4 http://statcvs.sf.net/ 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20 $Name: $ 21 Created on $Date: 2008/04/02 11:52:02 $ 22 */ 23 package net.sf.statcvs.util; 24 25 import java.util.ArrayList; 26 import java.util.Collections; 27 import java.util.Comparator; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 import java.util.TreeMap; 33 34 /** 35 * Utility class for storing a map from <code>Object</code>s to 36 * <code>int</code>s. 37 * This class makes it easy to sort by key or value, and provides 38 * useful features like {@link #sum()}, {@link #max()}, and 39 * percent calculation. 40 * <p> 41 * The keys must be comparable, for example <code>String</code>s. 42 * <p> 43 * Behaviour for <code>null</code> keys is unspecified. 44 * 45 * @author Richard Cyganiak 46 * @version $Id: IntegerMap.java,v 1.16 2008/04/02 11:52:02 benoitx Exp $ 47 */ 48 public class IntegerMap { 49 50 private final Map map = new TreeMap(); 51 private final Comparator comparator = new SortByValueComparator(map); 52 private int sum = 0; 53 private int max = 0; 54 55 /** 56 * Puts a value into the map, overwriting any previous value 57 * for the same key. 58 * 59 * @param key an <code>Object</code> which is used as key. 60 * @param value the <code>int</code> value to be stored at this key. 61 */ 62 public void put(final Object key, final int value) { 63 max = Math.max(max, value); 64 sum -= get(key); 65 sum += value; 66 map.put(key, new Integer(value)); 67 } 68 69 /** 70 * Gets a value from the map. Returns the value which was 71 * stored in the map at the same key before. If no value was 72 * stored for this key, 0 will be returned. 73 * 74 * @param key an <code>Object</code> which is used as key. 75 * @return the value for this key 76 */ 77 public int get(final Object key) { 78 final Integer result = (Integer) map.get(key); 79 if (result == null) { 80 return 0; 81 } 82 return result.intValue(); 83 } 84 85 /** 86 * Same as {@link #get(Object)}, but returns an <code>Integer</code>, 87 * not an <code>int</code>. 88 * 89 * @param key the key to get the value for 90 * @return the value wrapped in an <code>Integer</code> object 91 */ 92 public Integer getInteger(final Object key) { 93 return (Integer) map.get(key); 94 } 95 96 /** 97 * Gets the value stored at a key as a percentage of all values 98 * in the map. 99 * 100 * @param key the key to get the value for 101 * @return the value as a percentage of the sum of all values 102 */ 103 public double getPercent(final Object key) { 104 return (double) get(key) * 100 / sum; 105 } 106 107 /** 108 * Gets the value stored at a key as a percentage of the maximum 109 * value in the map. For the maximum value, this will return 110 * 100.0. For a value half as large as the maximum value, this 111 * will return 50.0. 112 * 113 * @param key the key to get the value for 114 * @return the value as a percentage of largest value in the map 115 */ 116 public double getPercentOfMaximum(final Object key) { 117 return get(key) * 100 / max; 118 } 119 120 /** 121 * Adds an <code>int</code> to the value stored at a key. 122 * If no value was stored before at this key, the <code>int</code> 123 * will be stored there. 124 * 125 * @param key the key to whose value <code>addValue</code> should be added 126 * @param addValue the <code>int</code> to be added 127 */ 128 public void addInt(final Object key, final int addValue) { 129 put(key, addValue + get(key)); 130 } 131 132 /** 133 * Same as <code>addInt(key, 1)</code> 134 * 135 * @param key the key whose value should be increased 136 */ 137 public void inc(final Object key) { 138 addInt(key, 1); 139 } 140 141 /** 142 * Same as <code>addInt(key, -1)</code> 143 * 144 * @param key the key whose value should be decreased 145 */ 146 public void dec(final Object key) { 147 addInt(key, -1); 148 } 149 150 /** 151 * Deletes a value from the map. This is different from 152 * <code>put(key, 0)</code>. Removing will reduce 153 * the size of the map, putting 0 will not. 154 * 155 * @param key the key that should be removed 156 */ 157 public void remove(final Object key) { 158 sum -= get(key); 159 map.remove(key); 160 } 161 162 /** 163 * Returns <code>true</code> if the map contains a value 164 * for this key. 165 * 166 * @param key the key to check for 167 * @return <code>true</code> if the key is in the map 168 */ 169 public boolean contains(final Object key) { 170 return map.containsKey(key); 171 } 172 173 /** 174 * Returns the number of key-value pairs stored in the map. 175 * 176 * @return the number of key-value pairs stored in the map 177 */ 178 public int size() { 179 return map.size(); 180 } 181 182 /** 183 * Returns a set view of the keys. The set will be in 184 * ascending key order. 185 * 186 * @return a <code>Set</code> view of all keys 187 */ 188 public Set keySet() { 189 return map.keySet(); 190 } 191 192 /** 193 * Returns an iterator on the keys, sorted by key ascending. 194 * 195 * @return an iterator on the keys 196 */ 197 public Iterator iteratorSortedByKey() { 198 return map.keySet().iterator(); 199 } 200 201 /** 202 * Returns an iterator on the keys, sorted by values ascending. 203 * 204 * @return an iterator on the keys 205 */ 206 public Iterator iteratorSortedByValue() { 207 final List keys = new ArrayList(map.keySet()); 208 Collections.sort(keys, comparator); 209 return keys.iterator(); 210 } 211 212 /** 213 * Returns an iterator on the keys, sorted by values descending. 214 * 215 * @return an iterator on the keys 216 */ 217 public Iterator iteratorSortedByValueReverse() { 218 final List keys = new ArrayList(map.keySet()); 219 Collections.sort(keys, comparator); 220 Collections.reverse(keys); 221 return keys.iterator(); 222 } 223 224 /** 225 * Returns the sum of all values in the map. 226 * 227 * @return the sum of all values in the map 228 */ 229 public int sum() { 230 return sum; 231 } 232 233 /** 234 * Returns the average of all values in the map. 235 * 236 * @return the average of all values in the map 237 */ 238 public double average() { 239 return (double) sum() / size(); 240 } 241 242 /** 243 * Returns the maximum value in the map. 244 * 245 * @return the maximum value in the map. 246 */ 247 public int max() { 248 return max; 249 } 250 251 /** 252 * Private utility class for comparing of map entries by value. 253 */ 254 private static class SortByValueComparator implements Comparator { 255 private final Map mapToBeSorted; 256 257 public SortByValueComparator(final Map map) { 258 this.mapToBeSorted = map; 259 } 260 261 public int compare(final Object o1, final Object o2) { 262 final int i1 = ((Integer) this.mapToBeSorted.get(o1)).intValue(); 263 final int i2 = ((Integer) this.mapToBeSorted.get(o2)).intValue(); 264 if (i1 < i2) { 265 return -1; 266 } else if (i1 > i2) { 267 return 1; 268 } 269 return 0; 270 } 271 } 272 }