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