View Javadoc

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 }